검색결과 리스트
글
우분투 커널 업데이트 후 VirtualBox가 제대로 동작되지 않을 때 해결방법(버전 5.08 이후)
리눅스(우분투) 운영체제에서 가상머신인 VirtualBox를 사용하다가 Kernel 업데이트 중 시스템 상에 영향을 주는 업데이트를 수행하게 되면 재부팅 이후 Virtualbox가 정상적으로 동작하지 않는 경우가 종종 발생합니다. 특히 아래와 같은 팝업과 동시에 아래의 명령어를 입력하라는 안내가 친절하게 뜨곤 하지요.
$sudo /sbin/vboxconfig
물론 위의 경우가 발생하였을 때 바로 Terminal을 실행한 후 명령어를 입력하면 리눅스 커널이 해당 부분을 다시 컴파일 하여 정상적으로 동작할 수 있도록 해줍니다. 그런데 VirtualBox가 5.08버전에서부터는 이 명령어를 입력해도 동작이 되지 않는 경우가 종종 발생합니다.
VirtualBox 5.08 버전 이후의 경우 이러한 경우가 나타나는 것으로 알려져 있는데 이 경우 아래의 명령어를 입력하면 다시 말끔하게 해결할 수 있다.
$ sudo /sbin/rcvboxdrv setup
'공대생의 팁' 카테고리의 다른 글
| Spectral Clustering Algorithm(스펙트럼 군집화 알고리즘) (9) | 2015.12.28 |
|---|---|
| File System 및 커널 수정을 gedit로 쉽게 하는 방법(sudo root 권한으로 gedit 실행) (0) | 2015.11.16 |
| [컴퓨터비전]이미지 변환시 DoF(Degrees of Freedom)에 대한 고찰 (0) | 2015.10.13 |
| IP v4 주소 0.0.0.0의 의미 (0) | 2015.09.27 |
| PHLASHNT.SYS 드라이버를 로드할 수 없습니다. 오류 코드: 1275 (1) | 2015.09.07 |
설정
트랙백
댓글
글
안드로이드 - Java 서버간 Object 객체 소켓 프로그래밍
Java를 기반으로 한 프로그래밍을 하다 보면 자신이 만든 Class 단위의 값을 전송하고 싶은 경우가 있습니다. 만약 서버가 C/C++ 기반으로 만들어진 경우 호환을 위해 Class 내의 값을 기본형인 int나 String으로 변환한 후 이를 Byte 값으로 변환하여 전송을 한 후 이 값을 받은 서버가 다시 C/C++에서 가공하기 편한 구조로 다시 변경하는 방식을 사용해야 되어서 프로그래밍을 할 때 다소 불편한 점이 있습니다.
만약 서버가 Java를 기반으로 한다면 프로그래밍의 방식이 약간은 쉽게 바꿀 수 있습니다. 안드로이드와 서버 모두 Java를 사용하므로 Class를 통째로 넘겨주어도 이를 그대로 사용할 수 있다는 것입니다. 이 기능을 구현해주는 것이 바로 이번 포스팅에서 다루게 될 ObjectInputStream과 ObjectOutputStream 입니다. 바로 예제를 통해 이를 수행해보도록 합니다.
먼저 Java 언어로 서버를 설계해보도록 합니다.
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 | import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { // TODO Auto-generated method stub try { int port = 8200; //서버에 사용할 포트 번호를 설정해줍니다. ServerSocket sock = new ServerSocket(port); //안드로이드 Client로부터 접속을 받을 준비를 합니다. Socket socket = sock.accept(); //Socket로부터 받게 되는 InputStream을 설정합니다. InputStream is = socket.getInputStream(); //InputStream의 최종 형식을 Object로 설정해줍니다. ObjectInputStream ois = new ObjectInputStream(is); //Socket로부터 받은 데이터를 Object로 수신합니다. String getString = (String)ois.readObject(); System.out.println("receive : " + getString); ois.close(); is.close(); socket.close(); sock.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } | cs |
다음으로 안드로이드에서 Java 서버로 Object를 전송할 수 있는 프로그램을 만들어봅니다.
activity_main.xml
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 76 77 78 79 80 81 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activitymain" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:text="IP주소" /> <EditText android:id="@+id/ipaddr" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="192.168.1.1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:text="PORT 번호" /> <EditText android:id="@+id/portnumber" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="8200" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="90dp" android:layout_height="wrap_content" android:text="보낼 내용" /> <EditText android:id="@+id/sendserv" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="시스템프로그램설계" /> </LinearLayout> <Button android:id="@+id/tryconnect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="connect!" android:onClick="OnClick" /> </LinearLayout> | cs |
MainActivity.java
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 76 77 78 | import java.io.ObjectOutputStream; import java.io.OutputStream; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity{ private Handler mHandler = new Handler(); private EditText ipaddr, portno, message; protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ipaddr = (EditText)findViewById(R.id.ipaddr); portno = (EditText)findViewById(R.id.portnumber); message = (EditText)findViewById(R.id.sendserv); } public void OnClick(View v) throws Exception{ switch(v.getId()){ case R.id.tryconnect: (new Connect()).start(); break; } } class Connect extends Thread { public void run() { String ip = ipaddr.getText().toString(); int port = Integer.parseInt(portno.getText().toString()); String output = message.getText().toString(); try { //서버에 접속합니다. Socket socket = new Socket(ip, port); //소켓으로부터 OutputStream을 설정합니다. OutputStream os = socket.getOutputStream(); //OutputStream을 Object 방식으로 전송하도록 설정합니다. ObjectOutputStream oos = new ObjectOutputStream(os); //Object를 Socket을 통해 값을 전송합니다. oos.writeObject(output); oos.close(); os.close(); socket.close(); } catch (Exception e) { // TODO Auto-generated catch block final String recvInput = "연결에 실패하였습니다."; mHandler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub setToast(recvInput); } }); } } } void setToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } } | cs |
결과는 아래와 같습니다.
Client(안드로이드)측
Server측
'안드로이드 > 애플리케이션 제작' 카테고리의 다른 글
| Fedora에서 Android Studio가 동작되지 않을 때[Unable to run mksdcard SDK tool] (0) | 2015.12.21 |
|---|---|
| Android Studio로 improt 한 후 컴파일 타겟 변경하기(failed to find target with hash string ...) (0) | 2015.11.06 |
| Linux(우분투)에서 Android Studio 빠르게 실행하는 방법(바로가기 추가하기) (0) | 2015.10.17 |
| 같은 공유기에 접속중인 안드로이드 기기 탐색 및 통신하기 (1) | 2015.10.16 |
| Error: The SDK Build Tools revision is too low for project (0) | 2015.10.10 |
설정
트랙백
댓글
글
안드로이드 프레임워크 프로그래밍(26) [System Service에서 Activity 함수 호출하기]
안드로이드 AIDL을 사용하여 RPC통신을 통해 Application 단계에서 Framework 단계의 method를 호출하는 방법에 대해 알아본 바 있습니다. 이번 포스팅에서는 Framework 단계에서 Application의 Activity에 존재하는 method를 호출하는 방법에 대해 알아보도록 하겠습니다.
포스팅을 시작하기에 앞서 이전에 사용하였던 Application 단계에서 Framework 단계의 기능을 사용한 바 있습니다. 이에 대한 자세한 내용은 아래 포스팅을 참조해주시길 바랍니다. 또한 본 포스팅의 예제 또한 아래 포스팅의 것을 사용하였음을 알립니다.
안드로이드 프레임워크 프로그래밍(4) [시스템서비스 추가하기]
안드로이드 Application을 실행하였을 때 Framework 단계에서 실행하고자 하는 method를 onCreate() 단계에서 등록을 합니다. 그 이후 System Service에서 특정 부분을 호출 받았을 때 Application의 Activity 내에 있는 함수를 실행하는 과정을 구현할 것입니다.
1. AIDL을 통해 Callback 함수 등록 및 해제 함수를 만들어줍니다.
/frameworks/base/core/java/android/os/ITestService.aidl
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 | /* * aidl file : frameworks/base/core/java/android/os/ITestService.aidl * This file contains definitions of functions which are exposed by service */ package android.os; import android.os.IActivityServiceCallback; interface ITestService { /** * {@hide} */ void setValue(int val); void execCallback(int val); /** * Often you want to allow a service to call back to its clients. * This shows how to do so, by registering a callback interface with * the service. */ boolean registerCallback(IActivityServiceCallback cb); /** * Remove a previously registered callback interface. */ boolean unregisterCallback(IActivityServiceCallback cb); } | cs |
Activity에서 실행하고자 하는 method는 registerCallback() method를 통해 System Service에 등록할 수 있습니다. execCallback()함수는 이후 Application에서 RPC를 통해 호출을 받은 후 Callback 기능을 구현하기 위해 만든 함수입니다.
2. Activity로부터 호출하고자 하는 함수를 구현할 IActivityServiceCallback.aidl을 생성합니다.
/frameworks/base/core/java/android/os/IActivityServiceCallback.aidl
1 2 3 4 5 6 7 8 9 10 11 12 13 | package android.os; /** * Example of a callback interface used by IActivityService to send * synchronous notifications back to its clients. Note that this is a * one-way interface so the server does not block waiting for the client. */ oneway interface IActivityServiceCallback { /** * Called when the service has a new value for you. */ void callActivityMethod(int value); } | cs |
위의 과정에서 만들어진 callActivityMethod() method는 이후 Activity에서 Callback 방식으로 구현될 것입니다. 다음으로 System Serivce에서 위의 새로 생성한 함수들을 구현해 보도록 하겠습니다.
/frameworks/base/services/java/com/android/server/TestService.java
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | /*TestService.java */ package com.android.server; import android.content.Context; import android.os.Handler; import android.os.IActivityServiceCallback; import android.os.ITestService; import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; public class TestService extends ITestService.Stub { private static final String TAG = "TestService"; private TestWorkerThread mWorker; private TestWorkerHandler mHandler; private Context mContext; RemoteCallbackList<IActivityServiceCallback> callbacks = new RemoteCallbackList<IActivityServiceCallback>(); public TestService(Context context) { super(); mContext = context; mWorker = new TestWorkerThread("TestServiceWorker"); mWorker.start(); Log.i(TAG, "Spawned worker thread"); } public boolean registerCallback(IActivityServiceCallback cb) throws RemoteException{ boolean flag = false; if(cb != null){ flag = callbacks.register(cb); } return flag; } public boolean unregisterCallback(IActivityServiceCallback cb) throws RemoteException{ boolean flag = false; if(cb != null){ flag = callbacks.unregister(cb); } return flag; } public void setValue(int val) { Log.i(TAG, "setValue " + val); Message msg = Message.obtain(); msg.what = TestWorkerHandler.MESSAGE_SET; msg.arg1 = val; mHandler.sendMessage(msg); } public void execCallback(int val){ Message msg = Message.obtain(); msg.what = TestWorkerHandler.CALLBACK; msg.arg1 = val; mHandler.sendMessage(msg); } private class TestWorkerThread extends Thread { public TestWorkerThread(String name) { super(name); } public void run() { Looper.prepare(); mHandler = new TestWorkerHandler(); Looper.loop(); } } private class TestWorkerHandler extends Handler { private static final int MESSAGE_SET = 0; private static final int CALLBACK = 1; @Override public void handleMessage(Message msg) { try { if (msg.what == MESSAGE_SET) { Log.i(TAG, "set message received: " + msg.arg1); } if (msg.what == CALLBACK) { int n = callbacks.beginBroadcast(); for(int i = 0; i < n ; i++){ try { Log.i(TAG, "callbacks.beginBroadcast()"); callbacks.getBroadcastItem(i).callActivityMethod(msg.arg1); } catch (RemoteException e) { e.printStackTrace(); } } callbacks.finishBroadcast(); } } catch (Exception e) { // Log, don't crash! Log.e(TAG, "Exception in TestWorkerHandler.handleMessage:", e); } } } } | cs |
RemoteCallbackList 클래스를 통해 Activity로부터 callback을 등록한 후 execCallback() method가 Application으로부터 호출되면 곧 System Service에서 등록한 callback을 실행하게 됩니다. 아래는 이를 구현한 Application 소스코드입니다.
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 76 77 78 79 | package com.example.test; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.IActivityServiceCallback; import android.os.ITestService; import android.os.RemoteException; import android.os.ServiceManager; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.util.Log; public class MainActivity extends Activity { private static final String DTAG = "HelloServer"; ITestService om; IActivityServiceCallback mCallback = new IActivityServiceCallback.Stub() { @Override public void callActivityMethod(int arg0) throws RemoteException { // TODO Auto-generated method stub final int value = arg0; mHandler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub setToast("callActivityMethod : " + value); } }); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); om = ITestService.Stub.asInterface(ServiceManager.getService("Test")); try{ Log.d(DTAG, "Going to call service"); om.setValue(20); om.registerCallback(mCallback); Log.d(DTAG, "Service called successfully"); }catch(Exception e){ Log.d(DTAG, "FAILED to call service"); e.printStackTrace(); } } public void OnClick(View v) throws RemoteException{ switch(v.getId()){ case R.id.button1: om.execCallback(100); break; } } void setToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } protected void onDestroy(){ super.onDestroy(); try { om.unregisterCallback(mCallback); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } | cs |
위 함수를 실행하면 다음과 같은 결과를 얻으실 수 있습니다.
'안드로이드 > 프레임워크' 카테고리의 다른 글
| 안드로이드 프레임워크 프로그래밍(27) [Fedora에서 AOSP 안드로이드 운영체제 컴파일하기] (0) | 2015.12.31 |
|---|---|
| Windows 환경에서 fastboot를 통해 Android 이미지 포팅(Fastboot in Windows 7) (3) | 2015.11.22 |
| Android에서 VSync 동작 원리 및 초기화 과정(5) (0) | 2015.09.20 |
| 안드로이드 프레임워크 프로그래밍(25) [Native 단계에서 Looper의 동작 원리] (0) | 2015.09.16 |
| SurfaceFlinger에서 DispSyncSource의 초기화 과정 (0) | 2015.09.12 |