우분투 커널 업데이트 후 VirtualBox가 제대로 동작되지 않을 때 해결방법(버전 5.08 이후)

공대생의 팁 2015. 11. 5. 22:57

 리눅스(우분투) 운영체제에서 가상머신인 VirtualBox를 사용하다가 Kernel 업데이트 중 시스템 상에 영향을 주는 업데이트를 수행하게 되면 재부팅 이후 Virtualbox가 정상적으로 동작하지 않는 경우가 종종 발생합니다. 특히 아래와 같은 팝업과 동시에 아래의 명령어를 입력하라는 안내가 친절하게 뜨곤 하지요.


$sudo /sbin/vboxconfig


물론 위의 경우가 발생하였을 때 바로 Terminal을 실행한 후 명령어를 입력하면 리눅스 커널이 해당 부분을 다시 컴파일 하여 정상적으로 동작할 수 있도록 해줍니다. 그런데 VirtualBox가 5.08버전에서부터는 이 명령어를 입력해도 동작이 되지 않는 경우가 종종 발생합니다.




 VirtualBox 5.08 버전 이후의 경우 이러한 경우가 나타나는 것으로 알려져 있는데 이 경우 아래의 명령어를 입력하면 다시 말끔하게 해결할 수 있다.


$ sudo /sbin/rcvboxdrv setup





300x250

안드로이드 - Java 서버간 Object 객체 소켓 프로그래밍

 Java를 기반으로 한 프로그래밍을 하다 보면 자신이 만든 Class 단위의 값을 전송하고 싶은 경우가 있습니다. 만약 서버가 C/C++ 기반으로 만들어진 경우 호환을 위해 Class 내의 값을 기본형인 int나 String으로 변환한 후 이를 Byte 값으로 변환하여 전송을 한 후 이 값을 받은 서버가 다시 C/C++에서 가공하기 편한 구조로 다시 변경하는 방식을 사용해야 되어서 프로그래밍을 할 때 다소 불편한 점이 있습니다.


 만약 서버가 Java를 기반으로 한다면 프로그래밍의 방식이 약간은 쉽게 바꿀 수 있습니다. 안드로이드와 서버 모두 Java를 사용하므로 Class를 통째로 넘겨주어도 이를 그대로 사용할 수 있다는 것입니다. 이 기능을 구현해주는 것이 바로 이번 포스팅에서 다루게 될 ObjectInputStreamObjectOutputStream 입니다. 바로 예제를 통해 이를 수행해보도록 합니다.


 먼저 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측





300x250

안드로이드 프레임워크 프로그래밍(26) [System Service에서 Activity 함수 호출하기]

안드로이드/프레임워크 2015. 10. 27. 17:09

 안드로이드 AIDL을 사용하여 RPC통신을 통해 Application 단계에서 Framework 단계의 method를 호출하는 방법에 대해 알아본 바 있습니다. 이번 포스팅에서는 Framework 단계에서 Application의 Activity에 존재하는 method를 호출하는 방법에 대해 알아보도록 하겠습니다.


 포스팅을 시작하기에 앞서 이전에 사용하였던 Application 단계에서 Framework 단계의 기능을 사용한 바 있습니다. 이에 대한 자세한 내용은 아래 포스팅을 참조해주시길 바랍니다. 또한 본 포스팅의 예제 또한 아래 포스팅의 것을 사용하였음을 알립니다.


안드로이드 프레임워크 프로그래밍(4) [시스템서비스 추가하기]

http://elecs.tistory.com/64


 안드로이드 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

 위 함수를 실행하면 다음과 같은 결과를 얻으실 수 있습니다.






300x250