<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>dpush &#187; joytune</title>
	<atom:link href="http://www.dpush.co.kr/author/joytune/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dpush.co.kr</link>
	<description>dpush</description>
	<lastBuildDate>Mon, 10 Aug 2015 05:48:24 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.1</generator>
	<item>
		<title>DPUSH를 사용한 미니그룹웨어</title>
		<link>http://www.dpush.co.kr/p1086/</link>
		<comments>http://www.dpush.co.kr/p1086/#comments</comments>
		<pubDate>Wed, 29 Jul 2015 07:58:41 +0000</pubDate>
		<dc:creator><![CDATA[joytune]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.dpush.co.kr/?p=1086</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box" style="background-attachment:scroll;background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;border-color:#eae9e9;border-bottom-width: 0px;border-top-width: 0px;border-bottom-style: solid;border-top-style: solid;padding-bottom:20px;padding-left:0px;padding-right:0px;padding-top:20px;"><div class="avada-row">DPUSH를 적용해서 인트라넷을 구성한 사례입니다.<br />
사전에 해당 업체의 임직원분들의 양해를 구해서 올리는 내용입니다.<br />
FeelCommunications 임직원분들께 감사드립니다. ^^</p>
<p><iframe src="https://www.youtube.com/embed/Kml4ysC8YjI" width="900" height="815" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>PC 브라우저와 안드로이드 어플에 동시에 푸시가 가능한 서비스 모델을 보여주고 있습니다.</div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.dpush.co.kr/p1086/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>안드로이드 채팅 샘플</title>
		<link>http://www.dpush.co.kr/p1056/</link>
		<comments>http://www.dpush.co.kr/p1056/#comments</comments>
		<pubDate>Wed, 22 Apr 2015 10:31:42 +0000</pubDate>
		<dc:creator><![CDATA[joytune]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.dpush.co.kr/?p=1056</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box" style="background-attachment:scroll;background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;border-color:#eae9e9;border-bottom-width: 0px;border-top-width: 0px;border-bottom-style: solid;border-top-style: solid;padding-bottom:20px;padding-left:0px;padding-right:0px;padding-top:20px;"><div class="avada-row">안녕하세요. 오늘은 새로운 안드로이드 채팅 샘플에 대해 포스팅합니다.<br />
앞서 소개했던 javascript 채팅과 연동되어 브라우저와 같이 채팅이 가능하며 샘플 코드임으로 약간의 버그(?)는 있을 수 있습니다.<br />
먼저 발급받은 <span style="color: #0000ff;"><strong>PRODUCTKEY 설정메뉴에서 &#8220;Customer Info사용 체크&#8221; 와 &#8220;클라이언트 메시지 체크&#8221;를 하는 것이 중요합니다.</strong></span> ^^<br />
버그에 대한 부분은 제보해주시면 정말 감사하겠습니다. 기본 샘플만 있고 소스가 함께 오픈되니 알맞게 수정해서 사용하시면 됩니다.</p>
<h1>1. DPUSH를 이용한 안드로이드 채팅 샘플 만들기</h1>
<h2>1.1  샘플 어플의 내용</h2>
<p>본 문서는 DPUSH 기반 안드로이드 채팅앱에 대해 설명합니다.</p>
<p>본 채팅앱은 사용자 로그인 후, 텍스트 메시지를 교환하는 기본적인 채팅 기능을 지원합니다. 또한, Product key 변경을 통해 채팅방 변경이 가능합니다.<br />
<img class="alignnone  wp-image-1057" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/chat4.png" alt="chat" width="285" height="507" /></p>
<p>“디푸시안드로이드” 라는 아이디로 로그인한 상태에서 메시지를 주고 받는 기능을 제공합니다.</p>
<p><a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/productkey.png"><img class="alignnone  wp-image-1059" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/productkey.png" alt="productkey" width="286" height="509" /></a></p>
<p>Product key을 설정/변경하는 기능을 제공합니다.</p>
<p><a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/login.png"><img class="alignnone  wp-image-1058" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/login.png" alt="login" width="286" height="509" /></a></p>
<p>로그인 정보(아이디, 나이, 성별)를 입력/변경하는 기능을 제공합니다.</p>
<p>해당 어플은 스토어에서 DPUSH로 검색하면 받을 수 있으며 스토어 주소는 다음과 같습니다.</p>
<p><a href="https://play.google.com/store/apps/details?id=kr.co.joytune.dpchat">https://play.google.com/store/apps/details?id=kr.co.joytune.dpchat</a></p>
<h1>2. Android 채팅 앱 중요 설명</h1>
<h2>2.1  앱 구조</h2>
<p>전체 소스를 참고하시기 바라며, 기본적으로 필요한 중요한 내용만을 설명합니다.</p>
<p>채팅앱은 아래와 같이 3개의 Activity들로 구성됩니다.</p>
<table border="1">
<tbody>
<tr style="background-color: #dddddd;">
<td width="187">Activity 이름</td>
<td width="450">내용</td>
</tr>
<tr>
<td width="187">DPushActivity</td>
<td width="450">채팅의 메인 Activity로서 메시지를 입력받고 수신된 메시지를 보여주는 기능을 수행합니다. 실제 화면 구성 및 메시지 통신은 DPushMainFragment 클래스에서 수행합니다.</td>
</tr>
<tr>
<td width="187">DPushProdKeyCheck</td>
<td width="450">Product key를 설정/변경하는 기능을 제공합니다. 설정된 key는 다음번 앱 수행시에도 그대로 적용됩니다.</td>
</tr>
<tr>
<td width="187">DPushLogin</td>
<td width="450">로그인 정보를 받아 서버 접속을 기능을 제공합니다.</td>
</tr>
</tbody>
</table>
<h2>2.2  메인 액티비티 (DPushActivity)</h2>
<p>DPushActivity는 크게 아래와 같은 기능들을 수행합니다.</p>
<table border="1">
<tbody>
<tr style="background-color: #dddddd;">
<td width="45">번호</td>
<td width="446">기능</td>
<td width="147">수행 클래스</td>
</tr>
<tr>
<td width="45">1</td>
<td width="446">Product key 설정/변경 및 서버 접속</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">2</td>
<td width="446">Login 정보 설정 및 변경</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">3</td>
<td width="446">메시지 수신 및 화면 출력</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">4</td>
<td width="446">사용자 메시지를 서버로 전송</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">5</td>
<td width="446">다른 사용자의 로그인/로그아웃/정보 변경 내용을 공지</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">6</td>
<td width="446">채팅방에 접속된 사용자들의 목록을 출력</td>
<td width="147">DPushMainFragment</td>
</tr>
<tr>
<td width="45">7</td>
<td width="446">스마트폰이 Sleep Mode일 경우에도 메시지 수신</td>
<td width="147">DPushActivity</td>
</tr>
</tbody>
</table>
<h3><strong>2.2.1  </strong><strong>Product key 설정 및 변경</strong></h3>
<p>앱 수행시 이미 저장된 키가 있으면 그것을 사용하고 그렇지 않으면 Default값인 “LIVEDEMOPUSH” 값을 사용합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public void onCreate(Bundle savedInstanceState) {
......
		// 이전에 설정된 Product key를 찾는다.
		SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
		mProdKey = sharedPref.getString(&quot;PRODUCT_KEY&quot;, &quot;LIVEDEMODPUSH&quot;);
......
}
</pre>
<p>설정된 Product key를 가지고 서버에 접속합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
private void connectDPClient() {
		if (client != null) {
			client.close();
			client = null;
			gi = null;
		}

		mProdKeyChecked = false;

		DPOptions dpopts = new DPOptions();
		dpopts.setResultcallback(actionOnConnect(mHandler));

		client = new DPClient(mProdKey, dpopts) {

			public void onConnected() {
				Log.d(TAG, &quot;onconnected................&quot;);
			}

			public void onDisconnected() {
				Log.d(TAG, &quot;onDisconnected................&quot;);
				if (!client.isConnected()) connect();
			}
		};

		client.connect();
</pre>
<p>서버와 연결이 정상적으로 수행되면 다음번에 동일한 Product key를 사용하기 위해 Activity 저장영역에 Key를 저장합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
	switch (msg.what) {
		case ACTION_ON_CONNECT:
			b = msg.getData();
			String errMessage = b.getString(&quot;errmessage&quot;);
			if (errMessage.isEmpty()) {
				// Product key를 store한다
			    SharedPreferences sharedPref = 
getActivity().getPreferences(Context.MODE_PRIVATE);
				SharedPreferences.Editor editor = sharedPref.edit();
				editor.putString(&quot;PRODUCT_KEY&quot;, mProdKey);
				editor.commit();

				startSignIn();
			}
		}
	};
};
</pre>
<h3><strong>2.2.2  </strong><strong>Login 정보 설정 및 변경</strong></h3>
<p>Login 정보를 설정 혹은 변경 위해 DPushActivity를 띄웁니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
	// Login 정보 설정을 위해 Login 창을 띄운다.
	private void startSignIn() {
		mUsername = &quot;&quot;;
		Intent intent = new Intent(getActivity(), DPushLogin.class);
		intent.putExtra(&quot;requestcode&quot;, REQUEST_LOGIN);
		startActivityForResult(intent, REQUEST_LOGIN);
	}
	
	// Login 정보 변경을 위해 Login 창을 띄운다.
	private void startUpdateUserinfo() {
		Intent intent = new Intent(getActivity(), DPushLogin.class);
		intent.putExtra(&quot;username&quot;, mUsername);
		intent.putExtra(&quot;userage&quot;, &quot;&quot; + mUserage);
		intent.putExtra(&quot;usergender&quot;, &quot;&quot; + mUsergender);
		intent.putExtra(&quot;requestcode&quot;, REQUEST_UPDATE_USERINFO);
		startActivityForResult(intent, REQUEST_UPDATE_USERINFO);
	}
</pre>
<p>로그인 창 Activity인 DPushActivity를 통해 받은 로그인 정보를 사용하여 Group을 오픈합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public void performOpenGroup() {
       . . . . . .
		// 그룹을 오픈한다
		else {
			GroupOptions gpopts = new GroupOptions();
			gpopts.setCustevent(true);
			gpopts.setSendevent(true);

			JSONObject cinfo = new JSONObject();
			try {
				cinfo.put(&quot;nickname&quot;, mUsername);
				cinfo.put(&quot;age&quot;, mUserage);
				if (&quot;1&quot;.equals(mUsergender)) cinfo.put(&quot;gender&quot;, &quot;M&quot;);
				else if (&quot;2&quot;.equals(mUsergender)) cinfo.put(&quot;gender&quot;, &quot;F&quot;);
				else cinfo.put(&quot;gender&quot;, &quot;P&quot;);
			}
			catch (Exception e) {
				e.printStackTrace();
			}
			gpopts.setCustinfo(cinfo);

			gi = client.openGroup(GRP_ID, gpopts, null);
			// 메시지가 수신될때 수행되는 callback 함수 등록
			gi.onReceive(ACT_ID, action(mHandler));
			// Group 오픈 요청에 대한 결과를 처리하는 callback 함수 등록
			gi.setCallback(actionOnGroupOpened(mHandler));
			// 채팅방에 사용자가 들어올때 수행되는 callback 함수 등록
			gi.setOnUserIn(actionOnUserIn(mHandler));
			// 채팅방에서 사용자가 나갈때 수행되는 callback 함수 등록
			gi.setOnUserOut(actionOnUserOut(mHandler));
			// 채팅방내 사용자정보가 변경될때 수행되는 callback 함수 등록
			gi.setOnUserUpdated(actionOnUserUpdated(mHandler));
		}
	}
</pre>
<h3><strong>2.2.3  </strong><strong>메시지 수신 및 화면 출력</strong></h3>
<p>(2)에서 메시지가 수신될 때 호출되는 “action()” callback 함수를 통해 수신된 메시지를 화면에 출력합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
private static Callback action(final Handler handler) {
		return new Callback() {
			@Override
			public void call(Object... args) {
				String message = (String) args[0];
				JSONObject custInfo = (JSONObject) args[2];
				String nickname;
				try {
					nickname = custInfo.getString(&quot;nickname&quot;);
				}
				catch (JSONException e) {
					return;
				}

				Message msg = Message.obtain(null, ACTION_SHOW_TEXTMESSAGE, 0, 0);
				Bundle b = new Bundle();
				b.putString(&quot;nickname&quot;, nickname);
				b.putString(&quot;message&quot;, message);
				msg.setData(b);

				if (message != null) {
					handler.sendMessage(msg);
				}
			}
		};
	}
</pre>
<p>화면 출력하는 부분은 아래와 같습니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public void onCreate(Bundle savedInstanceState) {
              ......
				case ACTION_SHOW_TEXTMESSAGE:
					b = msg.getData();
					addMessage(b.getString(&quot;nickname&quot;), b.getString(&quot;message&quot;));
					break;
				}
              ......
			};
		};
</pre>
<h3><a name="_Toc417481252"></a><strong>2.2.4  </strong><strong>사용자 메시지를 서버로 전송</strong></h3>
<p>사용자가 메시지를 입력하고 전송 버튼을 누르면 입력된 메시지를 서버로 전송합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
private void attemptSend() {
		if (null == mUsername) return;
		mTyping = false;

		String message = mInputMessageView.getText().toString().trim();
		if (TextUtils.isEmpty(mInputMessageView.getText())) {
			mInputMessageView.requestFocus();
			return;
		}
		mInputMessageView.setText(&quot;&quot;);

		// 메시지를 전송한다.
		sendTextMessage(message);
	}

	public void sendTextMessage(String textMessage) {
		if (mProdKey.isEmpty()) {
			startGetProdKey(&quot;&quot;);
		}
		gi.send(ACT_ID, textMessage);
		return;
	}
</pre>
<h3><a name="_Toc417481253"></a><strong>2.2.5  </strong><strong>다른 사용자의 로그인/로그아웃/정보 변경 내용을 공지</strong></h3>
<p>(2)에서 등록한 “actionOnUserIn()”, “actionOnUserOut()”, ““actionOnUserUpdated()” callback 함수를 통해 다른 사용자의 로그인/로그아웃/정보변경 내용을 화면에 출력합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
private static Callback actionOnUserIn(final Handler handler) {
		return new Callback() {
			@Override
			public void call(Object... args) {

				JSONObject custInfo = (JSONObject) args[1];
				String nickname, age;
				try {
					nickname = custInfo.getString(&quot;nickname&quot;);
					age = custInfo.getString(&quot;age&quot;);
				}
				catch (JSONException e) {
					return;
				}

				Message msg = Message.obtain(null, ACTION_ON_USERIN, 0, 0);
				Bundle b = new Bundle();
				b.putString(&quot;nickname&quot;, nickname);
				b.putString(&quot;age&quot;, age);
				msg.setData(b);

				if (nickname != null &amp;&amp; !nickname.isEmpty()) {
					handler.sendMessage(msg);
				}
			}
		};
	}

	private static Callback actionOnUserOut(final Handler handler) {
		return new Callback() {
			@Override
			public void call(Object... args) {

				JSONObject custInfo = (JSONObject) args[1];
				String nickname, age;
				try {
					nickname = custInfo.getString(&quot;nickname&quot;);
					age = custInfo.getString(&quot;age&quot;);
				}
				catch (JSONException e) {
					return;
				}

				Message msg = Message.obtain(null, ACTION_ON_USEROUT, 0, 0);
				Bundle b = new Bundle();
				b.putString(&quot;nickname&quot;, nickname);
				b.putString(&quot;age&quot;, age);
				msg.setData(b);

				if (nickname != null &amp;&amp; !nickname.isEmpty()) {
					handler.sendMessage(msg);
				}
			}
		};
	}

	private static Callback actionOnUserUpdated(final Handler handler) {
		return new Callback() {
			@Override
			public void call(Object... args) {

				JSONObject custInfo = (JSONObject) args[1];
				String nickname, age;
				try {
					nickname = custInfo.getString(&quot;nickname&quot;);
					age = custInfo.getString(&quot;age&quot;);
				}
				catch (JSONException e) {
					return;
				}

				Message msg = Message.obtain(null, ACTION_ON_USERUPDATED, 0, 0);
				Bundle b = new Bundle();
				b.putString(&quot;nickname&quot;, nickname);
				b.putString(&quot;age&quot;, age);
				msg.setData(b);

				if (nickname != null &amp;&amp; !nickname.isEmpty()) {
					handler.sendMessage(msg);
				}
			}
		};
	}
</pre>
<p>Callback 함수로부터 받은 메시지를 출력하는 부분은 아래와 같습니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public void onCreate(Bundle savedInstanceState) {
              ......
				case ACTION_ON_USERIN:
					b = msg.getData();
					addLog(&quot;'&quot; + b.getString(&quot;nickname&quot;) + &quot;(&quot; + b.getString(&quot;age&quot;) + &quot;)'님이 입장하셨습니다.&quot;);
					break;
				case ACTION_ON_USEROUT:
					b = msg.getData();
					addLog(&quot;'&quot; + b.getString(&quot;nickname&quot;) + &quot;(&quot; + b.getString(&quot;age&quot;) + &quot;)'님이 퇴장하셨습니다.&quot;);
					break;
				case ACTION_ON_USERUPDATED:
					b = msg.getData();
					addLog(&quot;'&quot; + b.getString(&quot;nickname&quot;) + &quot;(&quot; + b.getString(&quot;age&quot;) + &quot;)'님으로 대화명이 변경되었습니다.&quot;);
					break;
              ......
			};
		};
</pre>
<h3><a name="_Toc417481254"></a><strong>2.2.6  </strong><strong>채팅방에 접속된 사용자들의 목록을 출력</strong></h3>
<p>폰의 메뉴버튼을 통해 “Show userlist” 명령이 수행되면, 현재 접속된 사용자들의 목록을 출력합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
// 메뉴 버튼을 처리하는 함수
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
......
		else if (id == R.id.action_show_userlist) showUserList();
......
	}

	// 현재 접속된 사용자들의 목록을 화면에 출력
	private void showUserList() {
		JSONObject userList;
		userList = gi.getUserList();
		String userListResult = &quot;&quot;;

		int i = 0;
		try {
			Iterator&lt;String&gt; keys = userList.keys();
			while (keys.hasNext()) {
				String key = keys.next();
				JSONObject custInfo = userList.getJSONObject(key);
				String genderResult = &quot;&quot;;

				if (custInfo.has(&quot;gender&quot;)) {
					Log.d(&quot;DPushMainFragment&quot;, &quot;gender&quot; + custInfo.getString(&quot;gender&quot;));
					genderResult = custInfo.getString(&quot;gender&quot;);
				}

				if (&quot;M&quot;.equals(genderResult)) genderResult = &quot;남성&quot;;
				else if (&quot;F&quot;.equals(genderResult)) genderResult = &quot;여성&quot;;
				else genderResult = &quot;&quot;;

				userListResult += &quot;'&quot; + custInfo.getString(&quot;nickname&quot;) + &quot;(&quot; + genderResult + &quot;,&quot; + custInfo.getString(&quot;age&quot;) + &quot;)'&quot;;
				if (i &lt; userList.length() - 1) userListResult += &quot;, &quot;;
				i++;
			}
			addLog(&quot;현재 접속된 사용자는 &quot; + userListResult + &quot; 입니다.&quot;);
		}
		catch (JSONException e) {
			addLog(&quot;ERROR: 현재 접속된 사용자는 &quot; + userListResult + &quot; 입니다.&quot;);
		}
		return;
	}
</pre>
<h3><a name="_Toc417481255"></a><strong>2.2.7  </strong><strong>스마트폰이 Sleep Mode일 경우에도 메시지 수신</strong></h3>
<p>스마트폰이 SleepMode 로 진입했을때 서버와의 연결을 유지하기 위해 PowerManager의 WakeLock을 사용합니다. 이 코드는 셈플로 실 구현시는 battery 사용에 유의하셔야 합니다</p>
<pre class="brush: java; title: Code Example; notranslate">
PowerManager powerManager;
	PowerManager.WakeLock wakeLock;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		powerManager = (PowerManager) getSystemService(POWER_SERVICE);
		wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, &quot;DPushChatWakelockTag&quot;);
		wakeLock.acquire();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		wakeLock.release();
	}
</pre>
<h2><a name="_Toc417481256"></a>2.3  Product key 설정 액티비티 (DPushProdKeyCheck)</h2>
<p>Product key를 입력 받는 액티비티이며, 메인(DPushMainFragment) Activity로부터 이전 Product key를 받고, 변경 key를 전달합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public class DPushProdKeyCheck extends Activity {

	private EditText mProdKeyView;
	private String mProdKey;
	private boolean mIsBound = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_prodkeycheck);

		mProdKeyView = (EditText) findViewById(R.id.prodkey_input);

		Button prodKeyInButton = (Button) findViewById(R.id.prodkey_in_button);
		prodKeyInButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				setProdKey();
			}
		});
		mProdKey = getIntent().getStringExtra(&quot;prodkey&quot;);
		mProdKeyView.setText(getIntent().getStringExtra(&quot;prodkey&quot;));

		if (!getIntent().getStringExtra(&quot;errmessage&quot;).isEmpty()) 
mProdKeyView.setError(getIntent().getStringExtra(&quot;errmessage&quot;));
	}

	private void setProdKey() {
		mProdKeyView.setError(null);
		String prodkey = mProdKeyView.getText().toString().trim();

		// 유저아이디가 적합한지를 체크한다.
		if (TextUtils.isEmpty(prodkey)) {
			mProdKeyView.setError(getString(R.string.error_field_required));
			mProdKeyView.requestFocus();
			return;
		}
		Intent intent = new Intent();
		intent.putExtra(&quot;prodkey&quot;, prodkey);
		setResult(RESULT_OK, intent);
		finish();
	}
}
</pre>
<h2><a name="_Toc417481257"></a>2.4  로그인 설정 액티비티 (DPushLogin)</h2>
<p>로그인 정보를 설정/변경하는 입력 받는 Activity이며, 메인(DPushMainFragment) Activity로부터 이전 로그인 정보를 받고, 변경된 로그인 정보를 전달합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
public class DPushLogin extends Activity {

	private EditText mUsernameView;
	private EditText mUserageView;
	private String mUsername;
	private int mUserage;
	private int mUsergender = 1; // 1: 남성(기본), 2: 여성
	private boolean mIsBound = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_login);

		// 로그인 폼을 설정한다.
		mUsernameView = (EditText) findViewById(R.id.username_input);
		mUserageView = (EditText) findViewById(R.id.userage_input);

		Button signInButton = (Button) findViewById(R.id.sign_in_button);
		signInButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View view) {
				attemptLogin();
			}
		});

		int requestCode = getIntent().getIntExtra(&quot;requestcode&quot;, -1);
		if (requestCode == DPushMainFragment.REQUEST_UPDATE_USERINFO) {
			mUsernameView.setText(getIntent().getStringExtra(&quot;username&quot;));
			mUserageView.setText(getIntent().getStringExtra(&quot;userage&quot;));

			String usergender = getIntent().getStringExtra(&quot;usergender&quot;);
			RadioButton rbMale = (RadioButton) findViewById(R.id.radio_male);
			RadioButton rbFemale = (RadioButton) findViewById(R.id.radio_female);

			if (&quot;1&quot;.equals(usergender)) rbMale.setChecked(true);
			else if (&quot;2&quot;.equals(usergender)) rbFemale.setChecked(true);
		}
	}

	public void onRadioButtonClicked(View view) {
		boolean checked = ((RadioButton) view).isChecked();

		switch (view.getId()) {
		case R.id.radio_male:
			if (checked) mUsergender = 1;
			break;
		case R.id.radio_female:
			if (checked) mUsergender = 2;
			break;
		}
	}

	private void attemptLogin() {
		mUsernameView.setError(null);
		String username = mUsernameView.getText().toString().trim();

		// 유저아이디가 적합한지를 체크한다.
		if (TextUtils.isEmpty(username)) {
			mUsernameView.setError(getString(R.string.error_field_required));
			mUsernameView.requestFocus();
			return;
		}

		String userage = mUserageView.getText().toString().trim();
		if (TextUtils.isEmpty(userage)) {
			mUserageView.setError(getString(R.string.error_field_required));
			mUserageView.requestFocus();
			return;
		}

		try {
			mUserage = Integer.parseInt(userage);
		}
		catch (Exception e) {
			mUserageView.setError(getString(R.string.error_age_number_required));
			mUserageView.requestFocus();
			return;
		}
		mUsername = username;
		Intent intent = new Intent();
		intent.putExtra(&quot;username&quot;, mUsername);
		intent.putExtra(&quot;userage&quot;, &quot;&quot; + mUserage);
		intent.putExtra(&quot;usergender&quot;, &quot;&quot; + mUsergender);
		setResult(RESULT_OK, intent);
		finish();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
	}
}
</pre>
<h2><a name="_Toc417481258"></a>2.5  안드로이드 Manifest</h2>
<p>이제 위와 같은 기능을 사용하기 위해 Andorid Manifest file 을 수정합니다.</p>
<p>먼저 2.1에서 설명한 3개의 Activity를 명시합니다.</p>
<pre class="brush: xml; title: Code Example; notranslate">
&lt;application
        android:allowBackup=&quot;true&quot;
        android:debuggable=&quot;false&quot;
        android:icon=&quot;@drawable/dpush_logo&quot;
        android:label=&quot;@string/app_name&quot;
        android:theme=&quot;@android:style/Theme.Black.NoTitleBar&quot; &gt;

        &lt;activity
            android:name=&quot;kr.co.joytune.dpchat.DPushActivity&quot;
            android:screenOrientation=&quot;portrait&quot;
            android:label=&quot;DPush&quot; &gt;            
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
                &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

        &lt;activity
            android:name=&quot;kr.co.joytune.dpchat.DPushLogin&quot;
            android:label=&quot;@string/title_activity_login&quot;
            android:screenOrientation=&quot;portrait&quot;
            android:theme=&quot;@android:style/Theme.Black.NoTitleBar&quot; &gt;
        &lt;/activity&gt;
         
        &lt;activity
            android:name=&quot;kr.co.joytune.dpchat.DPushProdKeyCheck&quot;
            android:label=&quot;@string/title_activity_prodkey&quot;
            android:screenOrientation=&quot;portrait&quot;
            android:theme=&quot;@android:style/Theme.Black.NoTitleBar&quot; &gt;
        &lt;/activity&gt;

    &lt;/application&gt;
</pre>
<p>또한, 정의된 안드로이드 기능을 사용하기 위한 권한정보를 추가합니다</p>
<pre class="brush: xml; title: Code Example; notranslate">
&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
    &lt;!-- powermanager.wakelock 사용 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;
    &lt;!-- 네트웍 상태 확인 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
    &lt;!-- 폰정보 확인 : Context.TELEPHONY_SERVICE --&gt;
    &lt;uses-permission android:name=&quot;android.permission.READ_PHONE_STATE&quot; /&gt;
    &lt;!-- 부팅완료 확인 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot; /&gt;
</pre>
<h2>* 자신만의 채팅방을 만드려면?</h2>
<p>개발자이신 경우 직접 PRODUCTKEY를 받아서 소스상에서 수정하시면 됩니다.</p>
<p>먼저 간단한 가입을 통해 PRODUCTKEY를 받습니다.</p>
<p><a href="http://my.dpush.co.kr/my/login.php?cmd=joinform">DPUSH PRODUCTKEY 받기</a></p>
<p>기본적인 안드로이드 환경에 대한 설정은 사이트를 확인하세요.</p>
<p><a href="http://www.dpush.co.kr/1-2-android/">사이트 Document 확인</a></p>
<p>생성한 Android 프로젝트의 libs 폴더에 JavaLibrary 를 첨부합니다.</p>
<p>필요한 라이브러리는 &#8220;Java-WebSocket-1.3.0.jar&#8221; 와 &#8220;dpush-v0.x.jar&#8221; 입니다</p>
<p><a href="http://www.dpush.co.kr/downall/">사이트 Download</a></p>
<p>가입 후에 채팅을 위해서는 두가지 세팅이 필요합니다.</p>
<p>&#8220;Customer Info사용 체크&#8221; 와 &#8220;클라이언트 메시지 체크&#8221; 입니다.</p>
<p><a href="http://www.dpush.co.kr/setting/">설정방법 가이드 보기</a></p>
<p><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://www.dpush.co.kr/?wpdmdl=1053" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://www.dpush.co.kr/wp-content/plugins/download-manager/file-type-icons/arrow_down.png" /></div>        <div class="media-body"><strong class="ptitle">안드로이드채팅 <span class="label label-default" style="font-weight: 400;">2.43 MB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://www.dpush.co.kr/?wpdmdl=1053'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></p>
<h2></h2>
</div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.dpush.co.kr/p1056/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>안드로이드 푸시 (오늘의명언)</title>
		<link>http://www.dpush.co.kr/p1012/</link>
		<comments>http://www.dpush.co.kr/p1012/#comments</comments>
		<pubDate>Tue, 07 Apr 2015 04:04:42 +0000</pubDate>
		<dc:creator><![CDATA[joytune]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.dpush.co.kr/?p=1012</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box" style="background-attachment:scroll;background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;border-color:#eae9e9;border-bottom-width: 0px;border-top-width: 0px;border-bottom-style: solid;border-top-style: solid;padding-bottom:20px;padding-left:0px;padding-right:0px;padding-top:20px;"><div class="avada-row">
<h1><a name="_Toc416174207"></a>1. DPUSH를 이용한 안드로이드 푸시 샘플 만들기</h1>
<h2><a name="_Toc416174208"></a>1.1  시작 전에 필요한 작업들</h2>
<p>먼저 간단한 가입을 통해 PRODUCTKEY를 받습니다.</p>
<p><a href="http://my.dpush.co.kr/my/login.php?cmd=joinform">DPUSH PRODUCTKEY 받기</a></p>
<p>기본적인 안드로이드 환경에 대한 설정은 사이트를 확인하세요.</p>
<p><a href="http://www.dpush.co.kr/1-2-android/">사이트 Document 확인</a></p>
<p>생성한 Android 프로젝트의 libs 폴더에 JavaLibrary 를 첨부합니다.</p>
<p>필요한 라이브러리는 &#8220;Java-WebSocket-1.3.0.jar&#8221; 와 &#8220;dpush-v0.x.jar&#8221; 입니다</p>
<p><a href="http://www.dpush.co.kr/downall/">사이트 Download</a></p>
<h2><a name="_Toc416174209"></a>1.2  샘플 어플의 내용</h2>
<p>DPUSH 를 통해 최초 작업된 안드로이드 앱은 &#8220;오늘의 명언&#8221;이라는 어플입니다.</p>
<p>이 어플은 간단히 서버에서 전송되는 메시지를 Notification영역에 표시하고, 선택시 노출하는 기능만을 구현합니다.</p>
<p><a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/오늘의명언_1.png"><img class="alignnone  wp-image-1018" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/오늘의명언_1.png" alt="오늘의명언_1" width="309" height="550" /></a> <a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/오늘의명언_2.png"><img class="alignnone  wp-image-1017" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/오늘의명언_2.png" alt="오늘의명언_2" width="309" height="550" /></a></p>
<p>서버에서 특정 메세지를 보낼 경우 안드로이드 폰에 상단 Notification 영역에 메세지가 왔음을 알립니다.</p>
<p>해당 어플은 스토어에서 DPUSH로 검색하면 받을 수 있으며 스토어 주소는 다음과 같습니다.</p>
<p>https://play.google.com/store/apps/details?id=kr.co.joytune.dpush</p>
<h1><a name="_Toc416174210"></a>2. Android APP(오늘의명언) 중요 설명</h1>
<h2><a name="_Toc416174211"></a>2.1  안드로이드 Service</h2>
<p>전체 소스를 참고하시고 기본적으로 필요한 중요한 내용만을 설명합니다.</p>
<p>필요한 기능으로 정의된 내용은 아래와 같습니다.</p>
<ol>
<li>서버에서 메시지를 전송받을 수 있는 Client</li>
<li>메시지 수신시 Notification 영역에 받은 메시지를 알림</li>
<li>알림 확인시 화면에 해당 내용을 노출</li>
<li>어플 종료 또는 스마트폰 시작시 자동으로 어플을 실행시킬수 있는 기능</li>
<li>스마트폰이 Sleep Mode일때도 메시지를 수신 할 수 있는 기능</li>
</ol>
<p>우선 서버와의 접속을 위한 dpclient 는 서비스영역에 정의합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
private DPClient dpm;

	// GRP_ID(그룹명) 와 ACT_ID(액션명) 는 property에서 읽어서 가져옵니다.

	private void connect() {
		// 기 정의된 dpclient 가 없으면 생성한다
		if (this.client == null) {
			this.client = new DPClient('발급받은 PRODUCTKEY') {

				public void onConnected() {
					Log.d(TAG, &quot;onconnect................&quot;);
				}

				public void onDisconnected() {
					Log.d(TAG, &quot;ondisconnect................&quot;);
					// 종료시 재접속 요청(30초후)
					mHandler.sendEmptyMessageDelayed(0x8999, 30 * 1000);
				}

				public void onHeartbeat() {
					mHandler.sendEmptyMessage(0x7000);
				}
			};
		}

		// 서버와의 접속을 시도한다
		if (!client.isConnected()) {
			client.connect();
		}

		// 오픈된 그룹이면 정의된 ActionID 에 해당하는 callback만을 재정의한다 
		if (client.isOpened(GRP_ID)) {
			Log.d(TAG, &quot;is opened....&quot;);
			gi = client.getOpenedGroup(GRP_ID);
			gi.onReceive(ACT_ID, action(mHandler));
		}
		// 그룹을 오픈한다
		else {
			Log.d(TAG, &quot;is not opened....&quot;);
			gi = client.openGroup(GRP_ID);
			gi.onReceive(ACT_ID, action(mHandler));
		}
	}

</pre>
<p>메시지 도착시 Notification 영역에 노출하기 위한 기능을 추가합니다</p>
<pre class="brush: java; title: Code Example; notranslate">
/**
	 * 서버에서 메시지가 수신되었을때의 callback을 정의한다
	 * @param handler
	 * @return
	 */
	private static Callback action(final Handler handler) {
		return new Callback() {
			@Override
			public void call(Object... args) {
				String message = (String) args[0];
				if (message != null &amp;&amp; !&quot;&quot;.equals(message)) {
					handler.sendMessage(handler.obtainMessage(ACTION_SHOW_NOTIFICATION, message));
				}
			}
		};
	}

	public static final int		NOTIFICATION_ID				= 0x1234;
	private static final int	ACTION_SHOW_NOTIFICATION	= 0x5001;

	/**
	 * 알림영역에 Notification 을 노출한다
	 * @param title
	 * @param text
	 */
	private void showNotification(CharSequence title, CharSequence text) {

		// 알림 도착시 실행하고자 하는 작업(Intent)을 설정 
		Intent intent = new Intent(DPushService.this.getApplicationContext(), DPushAlarm.class);
		// - 필요한 parameter 설정
		intent.putExtra(&quot;NM&quot;, title.toString());
		intent.putExtra(&quot;MG&quot;, text.toString());
		// - 기존에 호출된 Intent 가 있으면 제거한다
		intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		// - 새로운 Activity를 생성하도록 한다
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		// PendingIntent 초기화
		PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

		// 메시지 도착을 알리기 위해 Notification을 사용한다
		// Notification Builder 객체생성
		NotificationCompat.Builder notibuilder = new NotificationCompat.Builder(getApplicationContext());
		// - 상태표시줄에 나타낼 아이콘
		notibuilder.setSmallIcon(R.drawable.dpush_logo);
		// - Notification 을 표시할 시각
		notibuilder.setWhen(System.currentTimeMillis());
		// - 상태표시줄에 나타낼 제목
		notibuilder.setContentTitle(title);
		// - 상태표시줄에 나타낼 내용
		notibuilder.setContentText(Html.fromHtml(text.toString()));
		// - 알림항목을 눌렀을때 해당 알림을 자동으로 해제시키도록 설정
		notibuilder.setAutoCancel(true);
		// - 알림항목을 눌렀을때 실행할 작업(Intent)
		notibuilder.setContentIntent(contentIntent);
		// - builder 를 통해 Notification 생성
		Notification notification = notibuilder.build();

		// - 알림도착시 소리
		notification.defaults |= Notification.DEFAULT_SOUND;

		// NotificationManager 객체 호출
		NotificationManager mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		// - 고유아이디를가지는 notification 을 표시
		mNM.notify(DPUSH_NOTIFICATION_ID, notification);
	}
</pre>
<p>메시지 도착시 Notification 영역에 노출하기 위한 기능을 추가합니다</p>
<p>시스템에 의해 서비스가 강제 종료 되었을때 앱을 재시작 시키기 위한 Alarm을 등록/해제 하는 기능을 추가합니다</p>
<pre class="brush: java; title: Code Example; notranslate">

	@Override
	public void onCreate() {
		super.onCreate();
		// 등록된 알람은 제거
		unregisterRestartAlarm();
	}

	@Override
	public void onDestroy() {
		...
		// 알람 등록
		registerRestartAlarm();

		super.onDestroy();
	}

	/**
	 * 서비스가 시스템에 의해서 또는 강제적으로 종료되었을 때 호출되어
	 * 알람을 등록해서 15초 후에 서비스가 실행되도록 한다.
	 */
	private void registerRestartAlarm() {
		Intent intent = new Intent(DPushService.this, DPushReceiver.class);
		intent.setAction(DPushReceiver.ACTION_DPUSH_RESTART);
		PendingIntent sender = PendingIntent.getBroadcast(DPushService.this, 0, intent, 0);

		long firstTime = SystemClock.elapsedRealtime();
		firstTime += 15 * 1000; // 15초 후에 알람이벤트 발생

		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 60 * 1000, sender);
	}

	/**
	 * 기존 등록되어있는 알람을 해제한다.
	 */
	private void unregisterRestartAlarm() {
		Intent intent = new Intent(DPushService.this, DPushReceiver.class);
		intent.setAction(DPushReceiver.ACTION_DPUSH_RESTART);
		PendingIntent sender = PendingIntent.getBroadcast(DPushService.this, 0, intent, 0);

		AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
		am.cancel(sender);
	}
</pre>
<p>스마트폰이 SleepMode 로 진입했을때 서버와의 연결을 유지하기 위해 PowerManager의 WakeLock을 사용합니다. 이 코드는 셈플로 실 구현시는 battery 사용에 유의하셔야 합니다</p>
<pre class="brush: java; title: Code Example; notranslate">

	private BroadcastReceiver screenoff;

	@Override
	public void onCreate() {

		super.onCreate();
		...

		screenoff = new BroadcastReceiver() {

			@Override
			public void onReceive(Context context, Intent intent) {
				// 스마트폰 화면이 켜졌을때
				if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
					WakeLocker.releaseWakeLock();
				}
				// 스마트폰 화면이 꺼졌을때
				else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
					WakeLocker.acquireWakeLock(context);
				}
			}
		};
		// Screen Off Receiver 를 등록
		IntentFilter offfilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
		offfilter.addAction(Intent.ACTION_SCREEN_ON);
		registerReceiver(screenoff, offfilter);
		...
	}

	@Override
	public void onDestroy() {
		...
		// Screen Off Receiver 를 해제
		unregisterReceiver(screenoff);

		super.onDestroy();
	}

	static class WakeLocker {

		private static PowerManager.WakeLock sCpuWakeLock;

		/**
		 * PowerManager.WakeLock 시작
		 * @param context
		 */
		static void acquireWakeLock(Context context) {
			PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
			if (!pm.isScreenOn()) {
				sCpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, context.getClass().getSimpleName());
				sCpuWakeLock.acquire();
			}
		}

		/**
		 * PowerManager.WakeLock 해제
		 */
		static void releaseWakeLock() {
			if (sCpuWakeLock != null &amp;&amp; sCpuWakeLock.isHeld()) {
				sCpuWakeLock.release();
			}
		}
	}

</pre>
<h2><a name="_Toc416174212"></a>2.2  안드로이드 Receiver</h2>
<p>위와 같은 서비스를 생성한 이후, 부팅완료, 네트웍 변경등의 상황 발생시 서비스를 재시작하기 위한 Receiver 를 생성합니다</p>
<pre class="brush: java; title: Code Example; notranslate">
public class DPushReceiver extends BroadcastReceiver {

	private static final String TAG = DPushReceiver.class.getSimpleName();

	public static final String ACTION_DPUSH_RESTART = &quot;kr.co.joytune.dpush.restart&quot;;

	@Override
	public void onReceive(Context context, Intent intent) {
		String action = intent.getAction();

		/* 서비스 재시작 */
		if (action.equals(DPushReceiver.ACTION_DPUSH_RESTART)) {
			Log.d(TAG, &quot;Service dead, but resurrection&quot;);
			Intent i = new Intent(context, DPushService.class);
			context.startService(i);
		}

		/* 스마트폰 부팅완료 */
		if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
			Log.d(TAG, &quot;ACTION_BOOT_COMPLETED&quot;);
			Intent i = new Intent(context, DPushService.class);
			context.startService(i);
		}

		/* 네트웍 변경 */
		if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
			try {
				ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
				NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
				if (activeNetInfo != null) {
					Intent i = new Intent(context, DPushService.class);
					context.startService(i);
				}
			}
			catch (Exception e) {
			}
		}
	}
}
</pre>
<h2><a name="_Toc416174213"></a>2.3  안드로이드 Manifest</h2>
<p>이제 위와 같은 기능을 사용하기 위해 Andorid Manifest file 을 수정합니다</p>
<p>생성된 위 Service와 Receiver 를 manifest 에 추가합니다.</p>
<pre class="brush: java; title: Code Example; notranslate">
&lt;service
            android:name=&quot;.DPushService&quot;
            android:enabled=&quot;true&quot;
            android:process=&quot;:remote&quot; &gt;
        &lt;/service&gt;

        &lt;receiver
            android:name=&quot;.DPushReceiver&quot;
            android:enabled=&quot;true&quot;
            android:exported=&quot;false&quot;
            android:label=&quot;RestartService&quot;
            android:process=&quot;:remote&quot; &gt;
            &lt;intent-filter&gt;
                &lt;action android:name=&quot;kr.co.joytune.dpush.restart&quot; /&gt;
                &lt;action android:name=&quot;android.net.conn.CONNECTIVITY_CHANGE&quot; /&gt;
                &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot; /&gt;
            &lt;/intent-filter&gt;
        &lt;/receiver&gt;
</pre>
<p>또한, 정의된 안드로이드 기능을 사용하기 위한 권한정보를 추가합니다</p>
<pre class="brush: java; title: Code Example; notranslate">
&lt;!-- 인터넷 사용 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
    &lt;!-- powermanager.wakelock 사용 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;
    &lt;!-- 네트웍 상태 확인 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
    &lt;!-- 폰정보 확인 : Context.TELEPHONY_SERVICE --&gt;
    &lt;uses-permission android:name=&quot;android.permission.READ_PHONE_STATE&quot; /&gt;
    &lt;!-- 부팅완료 확인 --&gt;
    &lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot; /&gt;
</pre>
<h1><a name="_Toc416174214"></a>3. Server API 연동</h1>
<h2><a name="_Toc416174215"></a>3.1  시작 전에 필요한 작업들</h2>
<p>Server API의 경우 PHP를 기본으로 설명합니다.</p>
<p>서버에 대한 부분은 BUSINESS SERVER API에서 &#8216;DPServer의 선언&#8217;과 &#8216;send&#8217;를 참고하시면 됩니다.</p>
<p><a href="http://www.dpush.co.kr/4-3-business-server-api/">사이트 Document 확인</a></p>
<p>Download의 Server API(Business Server)에서 PHP를 다운받아서 설치합니다.</p>
<p><a href="http://www.dpush.co.kr/downall/">사이트 Download</a></p>
<h2><a name="_Toc416174216"></a>3.2  오늘의 명언 보내기</h2>
<p>서버 API에서의 작업은 간단합니다.</p>
<p>발급받은 PRODUCTKEY를 넣고 send를 호출하면 됩니다.</p>
<pre class="brush: php; title: Code Example; notranslate">
&lt;?php
include &quot;dpmessage.php&quot;;
$dpmessage = new DPServer(&quot;발급받은 PRODUCTKEY&quot;);
$dpmessage-&gt;send('twise','tnoti',&quot;A great secret of success is to go through life as a man who never gets used up.&lt;br&gt;성공의 커다란 비결은 결코 지치지 않는 인간으로 인생을 살아가는 것이다.&lt;br&gt;알버트 슈바이처&quot;);
?&gt;
</pre>
<p><div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://www.dpush.co.kr/?wpdmdl=1008" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://www.dpush.co.kr/wp-content/plugins/download-manager/file-type-icons/arrow_down.png" /></div>        <div class="media-body"><strong class="ptitle">오늘의명언 <span class="label label-default" style="font-weight: 400;">1.31 MB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://www.dpush.co.kr/?wpdmdl=1008'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.dpush.co.kr/p1012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DPUSH로 만드는 JAVASCRIPT 채팅</title>
		<link>http://www.dpush.co.kr/p961/</link>
		<comments>http://www.dpush.co.kr/p961/#comments</comments>
		<pubDate>Wed, 01 Apr 2015 07:04:51 +0000</pubDate>
		<dc:creator><![CDATA[joytune]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.dpush.co.kr/?p=961</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box" style="background-attachment:scroll;background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;border-color:#eae9e9;border-bottom-width: 0px;border-top-width: 0px;border-bottom-style: solid;border-top-style: solid;padding-bottom:20px;padding-left:0px;padding-right:0px;padding-top:20px;"><div class="avada-row">1. 간단한 채팅 만들기<br />
1.1 시작 전에 필요한 작업들<br />
먼저 간단한 가입을 통해 PRODUCTKEY를 받습니다.<br />
<a href="http://my.dpush.co.kr/my/login.php?cmd=joinform" target="_blank">DPUSH PRODUCTKEY 받기</a></p>
<p>가입 후에 채팅을 위해서는 두가지 세팅이 필요합니다.<br />
&#8220;Customer Info사용 체크&#8221; 와 &#8220;클라이언트 메시지 체크&#8221; 입니다.<br />
<a href="http://www.dpush.co.kr/setting/" target="_blank">설정방법 가이드 보기</a></p>
<p>1.2 채팅 화면 HTML</p>
<p><a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/chat1.png"><img class="alignnone size-full wp-image-967" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/chat1.png" alt="chat1" width="935" height="485" /></a></p>
<p>위와 같이 간단히 메세지를 입력했을때 받을수 있는 간단한 채팅창을 만들어 보도록 하겠습니다.</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=EDGE&quot; /&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;form name=&quot;chatform&quot; onsubmit=&quot;return false;&quot;&gt;
&lt;div style=&quot;width:1020px; height:500px;&quot;&gt;
&lt;div id=&quot;chatscreen&quot; style=&quot;width:90%;height:90%;border:1px solid green;overflow:auto; float:left&quot;&gt;&lt;/div&gt;
&lt;input type=&quot;text&quot; name=&quot;chatinput&quot; id=&quot;chatinput&quot; style=&quot;width:80%&quot; onKeyPress=&quot;javascript:(event.keyCode == 13) ? talk(): null;&quot;/&gt;
			&lt;input type=&quot;button&quot; value=&quot;&gt;&gt;&quot; onclick=&quot;talk()&quot; style=&quot;width:10%&quot;&gt;&lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>위와 같은 간단한 html 을 작성합니다.</p>
<p>1.3 JAVASCRIPT<br />
소스안에 다음의 JAVASCRIPT를 추가하시면 됩니다.</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
&lt;script src=&quot;http://jslib.dpush.co.kr:9000&quot;&gt;&lt;/script&gt;
&lt;script&gt;
var client = new DPClient('발급받은 PRODUCTKEY');
var group = client.openGroup('chat-group',{'sendevent':true});
group.onReceive('chat-action', function(data, userid, custinfo) {
	var chatscreen = document.getElementById(&quot;chatscreen&quot;);
	chatscreen.innerHTML += data + &quot;
&quot;;
	chatscreen.scrollTop = chatscreen.scrollHeight; 
});
function talk() {
	var txt = document.getElementById(&quot;chatinput&quot;).value;
	document.getElementById(&quot;chatinput&quot;).value = '';
	group.send('chat-action', txt);
}
&lt;/script&gt;
</pre>
<p>var client = new DPClient(&#8216;발급받은 PRODUCTKEY&#8217;);<br />
이 부분에 가입시 발급받은 PRODUCTKEY를 입력합니다.</p>
<p>client.openGroup(&#8216;chat-group&#8217;,{&#8216;sendevent':true});<br />
client의 openGroup에서 sendevent를 true로 설정하셔야 client에서 메세지를 전송할 수 있게 됩니다.</p>
<p>1.4 FULL SOURCE</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=EDGE&quot; /&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;script src=&quot;http://jslib.dpush.co.kr:9000&quot;&gt;&lt;/script&gt;
&lt;script&gt;
var client = new DPClient('발급받은 PRODUCTKEY');
var group = client.openGroup('chat-group',{'sendevent':true});
group.onReceive('chat-action', function(data, userid, custinfo) {
	var chatscreen = document.getElementById(&quot;chatscreen&quot;);
	chatscreen.innerHTML += data + &quot;
&quot;;
	chatscreen.scrollTop = chatscreen.scrollHeight; 
});
function talk() {
	var txt = document.getElementById(&quot;chatinput&quot;).value;
	document.getElementById(&quot;chatinput&quot;).value = '';
	group.send('chat-action', txt);
}
&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
	&lt;form name=&quot;chatform&quot; onsubmit=&quot;return false;&quot;&gt;
&lt;div style=&quot;width:1020px; height:500px;&quot;&gt;
&lt;div id=&quot;chatscreen&quot; style=&quot;width:90%;height:90%;border:1px solid green;overflow:auto; float:left&quot;&gt;&lt;/div&gt;
&lt;input type=&quot;text&quot; name=&quot;chatinput&quot; id=&quot;chatinput&quot; style=&quot;width:80%&quot; onKeyPress=&quot;javascript:(event.keyCode == 13) ? talk(): null;&quot;/&gt;
			&lt;input type=&quot;button&quot; value=&quot;&gt;&gt;&quot; onclick=&quot;talk()&quot; style=&quot;width:10%&quot;&gt;&lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>2. CUSTOMER INFO 추가 (닉네임등의 개인정보 추가)<br />
2.1 CUSTOMER INFO<br />
CUSTOMER INFO는 참여한 그룹에 Client 개인 정보입니다. DPMessage 에서 고객의 Business를 적용 할 수 있는 유일한 수단입니다. 앞에서 간단한 채팅 예제 경우 완성도를 높이기 위해서 채팅에 관련된 nickname이 필요할 수 있습니다. 이러한 데이터를 DPMessage Server에 보내서 다른 Client와 Sync를 맞추는 작업이 필요합니다. 또한 Client가 챗방에 접속하거나 접속이 끊겼을 경우 해당 이벤트에 대한 내용도 Client들에게 전달해야 합니다.</p>
<p>자세한 CUSTOMER INFO의 내용은 사이트의 문서를 참고 하시면 됩니다.<br />
<a href="http://www.dpush.co.kr/3-1-customer-info/" target="_blank">CUSTOMER INFO DOCUMENT 보기</a></p>
<p>2.2 사용자 정보를 추가한 HTML 화면</p>
<p><a href="http://www.dpush.co.kr/wp-content/uploads/2015/04/chat2.png"><img class="alignnone size-full wp-image-968" src="http://www.dpush.co.kr/wp-content/uploads/2015/04/chat2.png" alt="chat2" width="1037" height="566" /></a></p>
<p>간단한 챗창에서 유저목록을 추가하여 화면을 구성하도록 하겠습니다.</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;style&gt;
body {font-size:12px; color:black;}
div {font-size:12px; color:black;}
.userchange {font-size:12px; color:black;}
.usernick {font-size:12px; color:blue;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body onload=&quot;init()&quot;&gt;
&lt;form name=&quot;chatform&quot; onsubmit=&quot;return false;&quot;&gt;
&lt;div style=&quot;width:1020px;height:505px;&quot;&gt;
&lt;div id=&quot;chatscreen&quot; style=&quot;width:800px;height:500px;border:1px solid green;overflow:auto; float:left&quot;&gt;
&lt;div id=&quot;simplediv&quot; style=&quot;display:none; background-color:#cccccc;top:50px;left:100px;position:absolute;border:4px solid black;width:600px;height:300px&quot;&gt;
			&lt;center&gt;
&lt;h2 style=&quot;margin:70px 0 20px 0px;&quot;&gt;Enter Your NickName!&lt;/h2&gt;
&lt;div id=&quot;alerttext&quot; name=&quot;alerttext&quot; style=&quot;color:red;margin:10px 0 10px 0px;&quot;&gt; &lt;/div&gt;
&lt;div style=&quot;width:300px;text-align:left;&quot;&quot;&gt;
					&lt;span style=&quot;width:60px;&quot;&gt;
						NickName : 
					&lt;/span&gt;
					&lt;span&gt;
						&lt;input type=&quot;text&quot; name=&quot;nickname&quot; style=&quot;width:200px;heigth:30px&quot;&gt;
					&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;width:300px;text-align:left;&quot;&gt;
					&lt;span&gt;
						Age : 
					&lt;/span&gt;
					&lt;span&gt;
						&lt;input type=&quot;text&quot; name=&quot;age&quot; style=&quot;width:30px;heigth:30px&quot;&gt;
					&lt;/span&gt;
					&lt;span style=&quot;margin-left:20px;&quot;&gt;
						gender : 
					&lt;/span&gt;
					&lt;span&gt;
						&lt;input type=&quot;radio&quot; name=&quot;gender&quot; value=&quot;M&quot;&gt;male &lt;input type=&quot;radio&quot; name=&quot;gender&quot; value=&quot;F&quot;&gt;female
&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin:20px 0 0 0&quot;&gt;
					&lt;input type=&quot;button&quot; value=&quot;enter&quot; onclick=&quot;setcookienick()&quot;&gt;
					&lt;input type=&quot;button&quot; value=&quot;cancel&quot; onclick=&quot;closeNickPop()&quot;&gt;&lt;/div&gt;
&lt;/center&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;chatusers&quot; style=&quot;width:200px;height:500px;border:1px solid green;overflow:auto;float:right;&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;margin:20px 0 0 0&quot;&gt;
	&lt;input type=&quot;hidden&quot; name=&quot;chatinput&quot; value=&quot;&quot;/&gt;
	&lt;input type=&quot;text&quot; name=&quot;chatinput&quot; id=&quot;chatinput&quot; style=&quot;width:800px&quot; onKeyPress=&quot;inputTalk()&quot;/&gt;
	&lt;input type=&quot;button&quot; value=&quot;&gt;&gt;&quot; onclick=&quot;talk()&quot;&gt;
	&lt;input type=&quot;button&quot; value=&quot;change nickname&quot; onclick=&quot;chgnick()&quot;&gt;&lt;/div&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>2.3 JAVASCRIPT<br />
소스 안에 JAVASCRIPT는 다음과 같습니다.</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
&lt;script src=&quot;http://jslib.dpush.co.kr:9000&quot;&gt;&lt;/script&gt;
&lt;script&gt;
var group = null;
var client = null;
var ischgnick = false;
var custinfo = null;
function roominit(custinfo) {

	client = new DPClient('발급받은 PRODUCTKEY'); 
	
	group = client.openGroup('chat-group', {
		'sendevent' : true,
		'custevent' : true,
		'custinfo' : custinfo,
	}, function(data) {
		writeUsers();
	});
	group.onReceive('chat-action', function(data, userid, custinfo) { 
		var nickname = &quot;&quot;;
		if (custinfo != null &amp;&amp; custinfo.nickname != null) {
			nickname = custinfo.nickname;
		}
		writeChat('&lt;font color=blue&gt;[' + nickname + '] : &lt;/font&gt;' + data + '');
	});
	// 사용자 login callback
	group.onUserIn(function(userid, custinfo) {
		if (custinfo.age == &quot;&quot;) {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님이 입장하셨습니다.&lt;/font&gt;');
		} else {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '(' + custinfo.age + ')\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님이 입장하셨습니다.&lt;/font&gt;');
		}
		writeUsers();
	});
	// 사용자 logout callback
	group.onUserOut(function(userid, custinfo) {
		if (custinfo.age == &quot;&quot;) {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님이 퇴장하셨습니다.&lt;/font&gt;');
		} else {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '(' + custinfo.age + ')\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님이 퇴장하셨습니다.&lt;/font&gt;');
		}
		writeUsers();
	});
	// 다른 client의 사용자 정보가 수정되었을 경우 해당 함수에 callback된다.
	group.onUserUpdated(function(userid, custinfo) {
		if (custinfo.age == &quot;&quot;) {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님으로 대화명이 변경되었습니다.&lt;/font&gt;');
		} else {
			writeChat('&lt;font class=&quot;usernick&quot;&gt;\'' + custinfo.nickname + '(' + custinfo.age + ')\'&lt;/font&gt;&lt;font class=&quot;userchange&quot;&gt; 님으로 대화명이 변경되었습니다.&lt;/font&gt;');
		}
		writeUsers();
	});
}
function talk() {
	var txt = document.getElementById(&quot;chatinput&quot;).value;
	document.getElementById(&quot;chatinput&quot;).value = '';
	group.send('chat-action', txt);
}
function writeChat(msg) {
	var chatscreen = document.getElementById(&quot;chatscreen&quot;);
	chatscreen.innerHTML += msg + &quot;
&quot;;
	chatscreen.scrollTop = chatscreen.scrollHeight;
}
function writeUsers(jsondata) {
	if (jsondata == null) {
		var _jsondata = group.getUserList();
	} else {
		var _jsondata = JSON.parse(jsondata);
	}
	var html = &quot;&quot;;
	var chatusers = document.getElementById(&quot;chatusers&quot;);
	
	for ( var socketid in _jsondata) {
		html += &quot; &quot;;
		if (_jsondata[socketid].nickname != '') {
			html += _jsondata[socketid].nickname;
			html += &quot;(&quot; + (_jsondata[socketid].age ? _jsondata[socketid].age : &quot;미입력&quot;) + &quot;)&quot;;
			html += &quot;[&quot; + (_jsondata[socketid].gender ? _jsondata[socketid].gender : &quot;미입력&quot;) + &quot;]&quot;;
			html += &quot;
&quot;;
		} else {
			html += socketid + &quot;
&quot;;
		}
	}
	chatusers.innerHTML = &quot;&lt;font class=\&quot;usernick\&quot;&gt;&quot; + html + &quot;&lt;/font&gt;&quot;;
}
function inputTalk() {
	if (event.keyCode == 13) {
		return talk();
	}
}
// 쿠키 생성
function setCookie(cName, cValue, cDay) {
	var expire = new Date();
	expire.setDate(expire.getDate() + cDay);
	cookies = cName + '=' + escape(cValue) + '; path=/ '; // 한글 깨짐을 막기위해 escape(cValue)를 합니다.
	if (typeof cDay != 'undefined')
		cookies += ';expires=' + expire.toGMTString() + ';';
	document.cookie = cookies;
}
// 쿠키 가져오기
function getCookie(cName) {
	cName = cName + '=';
	var cookieData = document.cookie;
	var start = cookieData.indexOf(cName);
	var cValue = '';
	if (start != -1) {
		start += cName.length;
		var end = cookieData.indexOf(';', start);
		if (end == -1)
			end = cookieData.length;
		cValue = cookieData.substring(start, end);
	}
	return unescape(cValue);
}

function init() {
	nickname = getCookie(&quot;nickname&quot;);
	age = getCookie(&quot;age&quot;);
	gender = getCookie(&quot;gender&quot;);

	if (nickname) {
		custinfo = {
			'nickname' : nickname,
			'age' : age,
			'gender' : gender
		};
		roominit(custinfo);
	} else {
		simplediv.style.display = &quot;block&quot;;
		document.chatform.nickname.focus();
	}
}
function setcookienick() {
	if (document.chatform.nickname.value == &quot;&quot;) {
		document.chatform.nickname.focus();
		document.getElementById(&quot;alerttext&quot;).innerHTML = &quot;Check your nickname.&quot;;
		return;
	}
	var _gender = &quot;&quot;;
	if (document.chatform.gender[0].checked) {
		_gender = document.chatform.gender[0].value;
	} else if (document.chatform.gender[1].checked) {
		_gender = document.chatform.gender[1].value;
	}
	setCookie(&quot;nickname&quot;, document.chatform.nickname.value);
	setCookie(&quot;gender&quot;, _gender);
	setCookie(&quot;age&quot;, document.chatform.age.value);
	custinfo = {
		'nickname' : document.chatform.nickname.value,
		'age' : document.chatform.age.value,
		'gender' : _gender
	}
	simplediv.style.display = &quot;none&quot;;
	if (ischgnick) {
		group.updateUser(custinfo);
	} else {
		roominit(custinfo);
	}
}
function closeNickPop() {
	simplediv.style.display = &quot;none&quot;;
}
function chgnick() {
	ischgnick = true;
	simplediv.style.display = &quot;&quot;;
}
&lt;/script&gt;
</pre>
<p>소스 라인이 많이 길어지긴 하지만 대부분 화면 처리와 쿠키값 처리를 위한 부분입니다.<br />
수정된 부분은 openGroup에서 custevent 를 true 설정해서 사용자 개인정보를 전달받도록 수정했으며 openGroup의 3번째 파라미터인 callback 함수를 등록하여 최초 접속 시에 writeUsers 란 함수에서 해당 유저의 목록을 보여주도록 변경되어 있습니다.</p>
<p>중요한 내용은 3가지의 event 함수를 등록하셔야 합니다.<br />
 group.onUserIn : 사용자가 접속했을때 발생되는 이벤트<br />
 group.onUserOut : 사용자가 접속 끊었을 때 발생되는 이벤트<br />
 group.onUserUpdated : 사용자가 개인정보를 변경했을 때 발생되는 이벤트<br />
<a href="http://www.dpush.co.kr/3-3-customer-info/" target="_blank">3종류 이벤트 함수 DOCUMENT 보기</a></p>
<p>NickName등의 개인 정보가 변경 되었을 경우 group.updateUser(custinfo); 를 호출하여 해당 내용은 전체 챗방에 접속한 Client들의 onUserUpdated 함수를 호출하게 됩니다.</p>
<p>FULL SOURCE는 다운 받으신 custinfochat.html을 참고하시면 됩니다.</p>
<p>3. 채팅의 서버공지 추가<br />
3.1 BUSINESS SERVER<br />
앞에서 나온 내용으로도 괜찮은(?) 간단한 채팅 어플이 완료되었습니다. 조금 더 심도있는 내용으로 BUSINESS SERVER 를 활용하는 공지메세지를 보내보도록 하겠습니다.<br />
BUSINESS SERVER 는 간단하게 DPUSH SERVER API를 이용해서 직접 메세지를 보낼 수 있는 간단한 서버라고 생각하시면 됩니다.<br />
<a href="http://www.dpush.co.kr/4-1-business-server/" target="_blank">BUSINESS SERVER DOCUMENT 보기</a></p>
<p>현 튜토리얼에서는 서버언어가 PHP로 가정해서 진행하도록 하겠습니다.<br />
DPUSH 사이트의 DOWNLOAD에서 Server API의 PHP 라이브러리를 다운받아서 서버에 업로드 합니다.</p>
<p>PHP로 간단한 공지의 소스는 다음과 같습니다.</p>
<pre class="brush: php; auto-links: false; gutter: true; title: Code Example; notranslate">
include &quot;[라이브러리위치]/dpmessage.php&quot;;
$dpmessage = new DPServer(&quot;발급받은 PRODUCTKEY&quot;);
$dpmessage-&gt;send('chat-group','chat-action-notice', &quot;Hello World!&quot;);
</pre>
<p>위에 소스는 간단한 예로 실제로 html의 input box에서 입력받도록 만들수도 있습니다.</p>
<p>3.2 JAVASCRIPT<br />
추가되는 JAVASCRIPT는 간단합니다.<br />
그룹 선언 이후에 다음의 onReceive 함수만 추가해 주면 됩니다.</p>
<pre class="brush: jscript; auto-links: false; gutter: true; title: Code Example; notranslate">
group.onReceive('chat-action-notice', function(data, userid, custinfo) { 
// 서버 공지에 대한 내용을 받는다.
	writeChat('&lt;font color=blue&gt;&lt;b&gt;[공지] : ' + data + '&lt;/b&gt;&lt;/font&gt;');
});
</pre>
<p>그룹은 메세지를 받는 전체 단위입니다. 즉 같은 그룹명으로 오픈된 전체 client는 send 메세지를 통해서 메세지를 전달 받게 됩니다. 여기서 action명을 통해서 해당 메세지를 받아서 처리하는 내용을 구분하게 됩니다. 예로 앞서서 chat-action과 chat-notice-action이 둘다 onReceive 함수로 등록되어 있는 경우 일반채팅과 공지를 둘 다 받아서 처리할 수 있습니다. chat-action만 등록되어 있는 경우 공지메세지를 받긴 하지만 처리하는 receive함수가 없기 때문에 푸시 메세지를 받기만 할 뿐 아무런 동작을 하지 않습니다.<br />
<a href="http://www.dpush.co.kr/2-4-receiver-action/" target="_blank">onReceive &#038; Send DOCUMENT 보기</a></p>
<p>FULL SOURCE는 다운 받으신 noticechat.html을 참고하시면 됩니다.</p>
<p>문서와 소스 받기 <div class='w3eden'><!-- WPDM Link Template: Default Template --><div class="wpdm-link-tpl link-btn [color]" data-durl="http://www.dpush.co.kr/?wpdmdl=977" >    <div class="media">        <div class="pull-left"><img class="wpdm_icon"   src="http://www.dpush.co.kr/wp-content/plugins/download-manager/file-type-icons/arrow_down.png" /></div>        <div class="media-body"><strong class="ptitle">채팅 TUTORIAL <span class="label label-default" style="font-weight: 400;">378.36 KB</span></strong>            <div><strong><a class='wpdm-download-link wpdm-download-locked [btnclass]' rel='noindex nofollow' href='http://www.dpush.co.kr/?wpdmdl=977'><i class=''></i>Download</a></strong></div>        </div>    </div></div><div style="clear: both"></div></div></div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.dpush.co.kr/p961/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DPUSH 오픈 베타를 시작합니다.</title>
		<link>http://www.dpush.co.kr/p248/</link>
		<comments>http://www.dpush.co.kr/p248/#comments</comments>
		<pubDate>Tue, 20 Jan 2015 13:52:05 +0000</pubDate>
		<dc:creator><![CDATA[joytune]]></dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.dpush.co.kr/?p=248</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<div class="fusion-fullwidth fullwidth-box" style="background-attachment:scroll;background-position:left top;background-repeat:no-repeat;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;border-color:#eae9e9;border-bottom-width: 0px;border-top-width: 0px;border-bottom-style: solid;border-top-style: solid;padding-bottom:20px;padding-left:0px;padding-right:0px;padding-top:20px;"><div class="avada-row">
<p style="text-align: center;">그동안 서비스 오픈을 위해 많은 시간을 준비했던 DPUSH 서비스가 오픈베타를 시작합니다.</p>
<p style="text-align: center;">DPUSH는 다음과 같은 서비스 특징을 가지고 있습니다.<br />
&#8220;쉽고 빠르다&#8221;, &#8220;다양한 매체 지원&#8221;, &#8220;간단한 절차&#8221;, &#8220;서버로그 NO&#8221;, &#8220;쉬운 프로그램&#8221;</p>
<p style="text-align: center;">베타 테스트 기간동안 무료로 가입하셔서 사용하실 수 있습니다.</p>
<p style="text-align: center;">차후 정식오픈은 따로 공지해 드리도록 하겠습니다.</p>
<p style="text-align: center;">최선의 노력과 서비스를 약속드리는 JOYTUNE이 되겠습니다.</p>
</div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.dpush.co.kr/p248/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
