Fedora에 이전 버전의 OpenJDK 설치하기(Install OpenJDK 7 in Fedora 23)

프로그래밍 팁 2015. 12. 22. 18:11

 Ubuntu의 경우 각 버전의 OpenJDK를 apt-get를 통해 제공하고 있습니다만 Fedora의 경우 최신 버전의 OpenJDK만이 dnf를 통해 제공되고 있습니다. AOSP(안드로이드 오픈소스 프로젝트)에서 안드로이드 운영체제를 컴파일하기 위해서는 특정 버전의 OpenJDK를 사용하여야 하는데 이게 아무리 최신 버전의 안드로이드 운영체제라 하더라도 항상 최신버전의 OpenJDK를 지원하지 않는 경우가 있습니다. 2015년 후반기에 등장한 최신 버전인 Marshmellow의 경우도 OpenJDK 1.7.0 버전을 요구하고 있기 때문에 현재 최신 버전인 OpenJDK 1.8.0에서는 컴파일을 진행할 수 없습니다.


 이번 포스팅에서는 2015년 후반기 최신 운영체제인 Fedora 23에 OpenJDK 1.7.0 버전을 설치해보도록 하겠습니다.


------------------------------------------------------------------------------------------------------------------------

 2015년 12월 현재 최신버전인 Fedora 23에는 기본적으로 최신버전인 1.8.0이 설치되어 있는 것을 확인할 수 있습니다.


$ java -version



Fedora 23 부터는 기존부터 사용되었던 설치 관리자인 yum이 새로운 설치 관리자인 dnf로 변경되었습니다. 이 과정 때문이지는 모르겠습니다만 Fedora 23에서는 OpenJDK 1.8.0 이전의 버전들은 dnf를 통해 제공을 하고 있지 않습니다. 우리는 이제 이전 버전의 OpenJDK를 직접 찾아 설치해보도록 하겠습니다. rpm 패키지들을 검색해주는 사이트인 rpmfind에 접속합니다.


https://www.rpmfind.net



 사이트에 접속한 후 검색창에 다음 단어들을 검색해줍니다.


java-1.7.0-openjdk-headless

java-1.7.0-openjdk

java-1.7.0-openjdk-devel


 위 단어를 검핵해보면 아래와 같이 해당 rpm의 최신버전이 가장 윗부분에 노출됩니다. 그 중 자신의 운영체제에 맞는 패키지를 선택해 다운로드 받습니다. 본 포스팅에서는 64비트의 Fedora를 사용중이므로 x86-64 버전을 다운로드 받았습니다.



 다운로드 받은 패키지의 설정에 따라 의존성이 달라질 수 있으며 이에 해당하는 부분들에 대한 설치가 진행되어야 합니다. 이 포스팅에서 진행하는 대로 설치하시는 것을 원하시는 분은 아래 rpm을 다운로드 해주시길 바랍니다.


java-1.7.0-openjdk-headless

ftp://195.220.108.108/linux/centos/7.2.1511/os/x86_64/Packages/java-1.7.0-openjdk-headless-1.7.0.91-2.6.2.3.el7.x86_64.rpm


java-1.7.0-openjdk

ftp://195.220.108.108/linux/centos/7.2.1511/os/x86_64/Packages/java-1.7.0-openjdk-1.7.0.91-2.6.2.3.el7.x86_64.rpm


java-1.7.0-openjdk-devel

ftp://195.220.108.108/linux/centos/7.2.1511/os/x86_64/Packages/java-1.7.0-openjdk-devel-1.7.0.91-2.6.2.3.el7.x86_64.rpm


 위 과정까지 진행하셨다면 패키지를 설치하기 전 의존성 충돌을 피하기 위해 아래의 패키지를 설치해줍니다.


# dnf install xorg-x11-fonts-Type1 libpng15


 만약 위와 같은 과정을 진행하지 않을 경우 아래와 같이 Failed dependencies Error가 발생하면서 의존성에 문제가 발생하는 경우가 있습니다. 이 경우 해당 dependency에 대해 설치를 해주어야 하는데 이는 위에서 알려드린 사이트 rpmfind에서 검색하면 관련 설치 패키지를 확인하실 수 있습니다.




 다음으로 다운로드 받은 패키지른 다음과 같이 순서대로 설치해줍니다.


# rpm -i --force --nodeps java-1.7.0-openjdk-headless-1.7.0.91-2.6.2.3.el7.x86_64.rpm

# rpm -i --force --nodeps java-1.7.0-openjdk-1.7.0.91-2.6.2.3.el7.x86_64.rpm

# rpm -i java-1.7.0-openjdk-devel-1.7.0.91-2.6.2.3.el7.x86_64.rpm


 아래의 명령어를 입력하시면 설치된 OpenJDK가 1.7.0 으로 변경된 것을 확인하실 수 있습니다.

$ java -version



300x250

Fedora에서 Android Studio가 동작되지 않을 때[Unable to run mksdcard SDK tool]

 Fedora 23 버전에서 Android Studio를 설치해야 될 일이 있어 한 번 해보려는데 생소한 오류가 발생하였습니다.


Unable to run mksdcard SDK tool.



 이 경우 아래와 같은 명령어를 수행하여 설치해줍니다.


 #dnf install compat-libstdc++-296.i686 compat-libstdc++-33.i686 compat-libstdc++-33.x86_64 ncurses-libs.i686


 설치후 안드로이드 스튜디오를 다시 실행하시면 정상적으로 동작되는 것을 확인하실 수 있습니다.


$ ~/android-studio/bin/studio.sh



300x250

[Hadoop] pom.xml로 maven 컴파일하기

프로그래밍 팁/Hadoop 2015. 11. 28. 11:18

 Hadoop을 설치하였을 때 사용자의 이해를 돕기 위해 별도로 예제를 마련해 두고 있습니다. maven을 사용해 Hadoop 소스코드를 컴파일 하기 위해서는 pom.xml을 사용해야 하는데 간단한 Hadoop 예제를 pom.xml로 컴파일 하는 방법을 알아보도록 하겠습니다.


1. 먼저 실행하고자 하는 Hadoop 소스코드를 구현합니다. 본 예제는 하둡의 예제 소스코드인 WordCount를 사용하였습니다.


/hadoop-example/src/main/java/elecs/tistory/com/WordCount.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
package elecs.tistory.com;
 
import java.io.IOException;
import java.util.StringTokenizer;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
 
public class WordCount {
 
  public static class TokenizerMapper 
       extends Mapper<Object, Text, Text, IntWritable>{
    
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
      
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
      }
    }
  }
  
  public static class IntSumReducer 
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();
 
    public void reduce(Text key, Iterable<IntWritable> values, 
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }
 
  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    if (otherArgs.length < 2) {
      System.err.println("Usage: <in> [<in>...] <out>");
      System.exit(2);
    }
    Job job = new Job(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    for (int i = 0; i < otherArgs.length - 1++i) {
      FileInputFormat.addInputPath(job, new Path(otherArgs[i]));
    }
    FileOutputFormat.setOutputPath(job,
      new Path(otherArgs[otherArgs.length - 1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}
cs


2. 다음으로 소스코드를 컴파일 하기 위한 pom.xml을 만듭니다.


/hadoop-example/pom.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                      http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-project</artifactId>
    <version>2.6.0</version>
  </parent>
  <groupId>elecs.tistory.com</groupId>
  <artifactId>hadoop-wordcount-example</artifactId>
  <version>2.6.0</version>
  <description>Apache Hadoop Wordcount Example</description>
  <name>Apache Hadoop Wordcount Example</name>
  <packaging>jar</packaging>
 
  <dependencies>
    <dependency>
      <groupId>commons-cli</groupId>
      <artifactId>commons-cli</artifactId>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
      <version>${project.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
      <scope>test</scope>
      <type>test-jar</type>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <scope>test</scope>
      <type>test-jar</type>
    </dependency>
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-hdfs</artifactId>
      <scope>runtime</scope>
    </dependency>
    <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-hdfs</artifactId>
       <scope>test</scope>
       <type>test-jar</type>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-yarn-server-tests</artifactId>
       <scope>test</scope>
       <type>test-jar</type>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-mapreduce-client-app</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-mapreduce-client-app</artifactId>
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
    <dependency>
      <groupId>com.sun.jersey.jersey-test-framework</groupId>
      <artifactId>jersey-test-framework-grizzly2</artifactId>
      <scope>test</scope>
    </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-mapreduce-client-hs</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.hsqldb</groupId>
       <artifactId>hsqldb</artifactId>
       <scope>provided</scope>
     </dependency>
     <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <scope>provided</scope>
     </dependency>
  </dependencies>
 
  <!--
  자신이 main으로 설정하고자 하는 class의 이름을 package경로와 함께 표기합니다.
  -->
  <build>
   <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-jar-plugin</artifactId>
      <configuration>
       <archive>
         <manifest>
           <mainClass>elecs.tistory.com.WordCount</mainClass>
         </manifest>
       </archive>
     </configuration>
    </plugin>
   </plugins>
   </build>
</project>
cs


3. 위 과정까지 진행하였다면 다음으로 maven을 사용해 Hadoop 소스코드를 컴파일합니다.


# mvn clean

 명령어 수행 후 target폴더가 생성되고 그 안에 jar 파일이 생성되었다면 컴파일에 성공한 것입니다.



 4. 다음으로 WordCount를 수행하기 위한 예제를 만듭니다.


# vi hello.txt




 5. hello.txt 예제 파일을 만든 후 hdfs에 파일을 전송합니다.


# hdfs dfs -mkdir /input

# hdfs dfs -copyFromLocal hello.txt /input


 6. hadoop 명령어를 실행하여 예제를 실행합니다.


# hadoop jar target/hadoop-wordcount-example-2.6.0.jar /input/hello.txt /output



7. 완성된 결과물을 Local 폴더에 저장합니다.


# hdfs dfs -getmerge /output result.txt

# cat result.txt


 아래와 같은 결과가 출력되면 Hadoop이 정상적으로 동작한 것입니다.




300x250

Windows 환경에서 fastboot를 통해 Android 이미지 포팅(Fastboot in Windows 7)

안드로이드/프레임워크 2015. 11. 22. 02:24

 Linux 환경에서 안드로이드 운영체제를 컴파일 하다 보니 안드로이드 이미지 포팅을 Linux로만 하게 되다보니 Windows 환경에서는 어떻게 하면 되는지 궁금했었는데 마침 기회가 되어 포스팅을 하게 되었습니다. 이번 포스팅에서는 Windows 환경에서 안드로이드 커널 이미지를 fastboot를 통해 설치해 보도록 합니다.


안드로이드 기기 : LG NEXUS 5

빌드 버전 : KitKat 4.4.4(r2)

운영체제 : Windows 7 SP1


 포스팅을 시작하기에 앞서 안드로이드 운영체제를 컴파일하여 이미지를 얻어내는 과정은 이전에 설명드렸던 포스팅을 참조해 주시길 바랍니다.


안드로이드 프레임워크 프로그래밍(3) [NEXUS5에 소스 빌드하기]

http://elecs.tistory.com/59


  1. 컴파일을 통해 완셩된 안드로이드 운영체제 이미지를 얻어냅니다. 이는 아래의 경로에서 얻으실 수 있습니다.


~/kitkat/out/target/product/hammerhead/


위에서 확인하실 수 있는 이미지(img) 파일 5개와 android-info.txt를 가져옵니다.


2. Windows 환경에서 Android SDK가 설치되어 있어야 합니다. Android SDK Manager를 실행하여 최하단 메뉴에 있는 Google USB Driver를 설치합니다.



3. 환경번수를 설정해줍니다. 컴퓨터에서 마우스 우측 클릭후 '속성'을 클릭합니다.



4. '고급 시스템 설정'을 클릭합니다.



5. 시스템 속성에서 '고급' 탭을 선택한 후 '환경 변수'를 클릭합니다.



6. 환경변수 창에서 시스템변수(S) 내에 Path를 더블클릭합니다.




7. 변수 값의 뒷부분에 다음 값을 추가합니다.


C:\Program Files\Android\android-sdk\platform-tools;


※주의!!

 절대로 변수 값의 내용을 지우시면 안됩니다! 만약 실수로 변수 값을 덮어쓰셨다면 바로 취소 버튼을 누릅니다. 만약 기존의 환경변수를 덮어쓰기로 모두 삭제할 경우 연결된 프로그램들이 동작을 하지 못하게 되는 참사가 발생합니다!

 만약 실수로 덮어쓰기 후 확인 버튼을 눌러 변수가 지워지신 분들은 절대로 당황하지 마시고 제가 이전에 포스팅한 내용을 따라가며 원래 환경 변수값을 복구하시길 바랍니다.


[윈도7] 환경변수 path 삭제시 복구하는 방법 ← 클릭하시면 새창으로 이동합니다.


========================================================================================================


8. 이번에는 안드로이드 운영체제 이미지가 위치하는 경로를 설정합니다. 아래 화면에서 '새로 만들기(W)'를 클릭합니다.

 

 

9. 새 시스템 변수의 변수 이름은 'ANDROID_PRODUCT_OUT'로, 변수 값은 안드로이드 커널 이미지가 위치한 파일 경로를 입력합니다. 본 포스팅에서는 E:\ 디스크에 안드로이드 커널 이미지를 두었습니다.



10. 이로서 Windows 환경에서 안드로이드 기기에 운영체제 이미지를 포팅할 준비를 마쳤습니다. 자신의 기기를 Fastboot 모드로 설정한 후 USB로 연결합니다.



11. Windows 운영체제가 안드로이드의 Fastboot 상태를 인식하게 되면 '드라이버 소프트웨어 설치'를 진행합니다. 아래와 같이 'Andorid Bootloader Interface'가 사용 준비 완료가 되기를 기다립니다.



12. CMD 창을 열어 다음과 같이 입력합니다.


> fastboot flashall



 위와 같은 화면이 나온다면 여러분들은 Windows 환경에서 fastboot를 통한 이미지 설치를 완료한 것입니다!


300x250

[Hadoop]Fedora 23 버전에서 Hadoop 2.7.1 설치하기(Install Hadoop 2.7.1 in Fedora 23)

프로그래밍 팁/Hadoop 2015. 11. 21. 10:37

 Fedora가 yum을 버리고 dnf를 사용하는 등 세세한 변화가 있어 이러한 환경에서 Hadoop을 설치하는 자세한 방법을 찾으면서 포스팅 해 보았습니다.


- 개발환경

운영체제 : Fedora 23

하둡 : Hadoop 2.7.1

ProtoBuffer : Protoc 2.5.0

JAVA : Java Development Kit 8


1. 시작하기에 앞서 dnf를 통해 아래의 프로그램드을 설치해주세요.


# dnf update

# dnf install gcc gcc-c++ automake kernel-devel openssl-devel cmake


2. 1.7+ 버전 이상의 Java를 설치합니다. 본 포스팅에서는 최신 버전의 JDK 8을 설치하였으며 Fedora 23의 경우 기본 설치된 JDK를 사용하시면 됩니다.


$ java -version



3. Maven 3.0 이상의 버전을 설치합니다. 본 포스팅에서는 Maven 3.3.9를 설치합니다.


# wget http://apache.tt.co.kr/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz

# tar -xzf apache-maven-3.3.9-bin.tar.gz

# mv apache-maven-3.3.9 /usr/local


4. ProtocolBuffer를 설치합니다. Hadoop 2.7.1의 경우 ProtocolBuffer 2.6.1을 설치해야 합니다.


# wget https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.gz

# tar -xzf protobuf-2.5.0.tar.gz

# mv protobuf-2.5.0 /usr/local/lib

# cd /usr/local/lib/protobuf-2.5.0

# ./configure

# make -j4

# make check

# make install

# make ldconfig


 5. Fedora에 기본으로 깔려있는ProtocolBuffer가 있다면 삭제 후 새로 설치한 ProtocolBuffer을 설정해줍니다.


# rm /usr/bin/protoc

# update-alternatives --install "/usr/bin/protoc" "protoc" "/usr/local/bin/protoc" 1

# protoc --version



6. bashrc 파일을 수정하여 설치한 Maven과 ProtocolBuffer를 사용할 수 있도록 설정합니다.


# vi ~/.bashrc


export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

export M2_HOME=/usr/local/apache-maven-3.3.9

export PATH=$M2_HOME/bin:$PATH


 

7. Hadoop 2.7.1을 다운로드 받은 후 압축을 풀어줍니다.


$ wget http://apache.mirror.cdnetworks.com/hadoop/common/hadoop-2.7.1/hadoop-2.7.1-src.tar.gz

$ tar -xzf hadoop-2.7.1-src.tar.gz

$ mv hadoop-2.7.1-src ~/

$ cd ~/hadoop-2.7.1-src


8. 이제 Hadoop을 컴파일 합니다. 컴파일 명령어는 아래와 같이 입력해줍니다.


# mvn clean package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip=true



 위의 화면과 같이 끝까지 수행하게 되면 Hadoop의 컴파일이 완료된 것입니다. 이제 Hadoop-dist 폴더를 확인하시면 컴파일된 Hadoop이 있는 것을 확인하실 수 있습니다.




 이제 컴파일된 Hadoop을 자신이 원하는 환경대로 구현을 하면 되겠습니다.

300x250

[Hadoop]JDK 8 버전에서 Hadoop 2.6.2 컴파일시 에러 해결방법

프로그래밍 팁/Hadoop 2015. 11. 19. 12:01

 버전이 높아질 수록 다양한 기능이 제공되기도 합니다만 때로는 호환성에 문제가 생겨 프로그램이 정상적으로 동작되지 않는 경우가 발생합니다. 아래와 같은 경우 Java Development Kit 8에서 hadoop을 컴파일하게 되었을 때 발생하는 에러입니다.


-개발환경

운영체제    : Ubuntu 12.04(64-bit)

하둡        : Hadoop 2.6.2

ProtoBuffer : Protoc 2.5.0

JAVA       : Java Development Kit 8


[INFO] Apache Hadoop Annotations ......................... FAILURE [4.086s]

---

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.8.1:jar (module-javadocs) on project hadoop-annotations: MavenReportException: Error while creating archive:

[ERROR] Exit code: 1 - C:\hadoop-src\hadoop-common-project\hadoop-annotations\sr

c\main\java\org\apache\hadoop\classification\InterfaceStability.java:27: error:

unexpected end tag: </ul>

[ERROR] * </ul>

[ERROR] ^

[ERROR]

[ERROR] Command line was: "C:\Program Files\Java\jdk1.8.0_05\jre\..\bin\javadoc.exe" -J-Dhttp.proxySet=true -J-Dhttp.proxyHost=proxy -J-Dhttp.proxyPort=3128 @op

tions @packages

[ERROR]

[ERROR] Refer to the generated Javadoc files in 'C:\hadoop-src\hadoop-common-project\hadoop-annotations\target' dir.

[ERROR] -> [Help 1]

[ERROR]

[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.

[ERROR] Re-run Maven using the -X switch to enable full debug logging.

[ERROR]

[ERROR] For more information about the errors and possible solutions, please read the following articles:

[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

[ERROR]


 위의 에러가 발생하는 이유는 Java Development Kit 8에서부터는 이전 버전에 비해 좀 더 엄격해져서 위의 태그 </ul>이 JDK8에서는 맞지 않아 에러를 발생시킨 경우 입니다. 이 경우 아래와 같이 명령어를 추가하면 간단하게 해결하실 수 있습니다.


$ mvn clean package -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip=true


300x250

OpenCV 최신 버전에서 Python으로 SIFT, SURF 사용하기(Install OpenCV 3.0 in Ubuntu)

프로그래밍 팁 2015. 11. 18. 16:07

 최신 버전의 OpenCV 라이브러리를 사용하여 Python 환경에서 SIFT 알고리즘을 수행하려 해보았더니 아래와 같은 화면이 출력됩니다.




 OpenCV 3.0.0 버전 이후에는 이전 버전에서 사용할 수 있었던 일부 라이브러리의 사용이 제한되어 있습니다. 자주 사용되는 SIFT와 SURF 또한 이에 해당되어 OpenCV 최신 버전을 그대로 설치하면 이를 바로 사용할 수 없습니다. 최신 버전의 OpenCV에서 이를 사용하기 위해서는 opencv_contrib을 추가적으로 설정해 주어야 합니다.


 1. OpenCV 최신 버전을 설치하기 위해 아래의 프로그램들을 설치합니다.


$ sudo apt-get install build-essential cmake git pkg-config libjpeg8-dev libtiff4-dev libjasper-dev libpng12-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libatlas-base-dev gfortran python2.7-dev


 2. Python 2.X 버전을 설치합니다. 3.X 버전의 경우 동작이 되지 않는 경우가 종종 발생한다는 점을 유의하셔야 합니다. apt-get에서는 2.X 버전을 제공합니다.


$sudo apt-get install python


 3. Python 패키지 매니저인 pip를 설치합니다.


$ wget https://bootstrap.pypa.io/get-pip.py

$ sudo python get-pip.py


 4. 기존 Python OpenCV의 라이브러리와는 별도로 동작할 수 있게 하는 virtualenv와 virtualenvwrapper를 설치합니다.


$ sudo pip install virtualenv virtualenvwrapper


 5. 설치한 virtualenv와 virtualenvwrapper가 항상 수행될 수 있도록 bash를 수정합니다.


$ vi ~/.bashrc



 6. 수정한 bashrc를 바로 적용합니다.


$source ~/.bashrc


 7. 독립된 별도의 Python OpenCV 라이브러리 환경을 만들기 위한 가상 환경을 생성합니다.


$mkvirtualenv cv


 8. 최신 버전의 OpenCV 버전을 다운로드 받아 OpenCV 폴더에 압축을 풉니다.


http://opencv.org/downloads.html


 또는 Github를 통해 최신 버전의 OpenCV 소스코드를 다운로드 받습니다.


$ cd ~

$ git clone https://github.com/Itseez/opencv.git

$ cd opencv

$ git checkout 3.0.0


 9. 이전 버전의 OpenCV 라이브러리를 사용할 수 있도록 해주는 opencv_contrib를 다운로드 받습니다.


$ cd ~

$ git clone https://github.com/Itseez/opencv_contrib.git

$ cd opencv_contrib

$ git checkout 3.0.0


 10. 이제 본격적으로 OpenCV 라이브러리를 설치해 보도록 합니다. 아래와 같이 cmake를 통해 Makefile을 구성합니다. 이 과정에서 위에서 받은 opencv_contrib을 설정해줍니다.


$ cd ~/opencv

$ mkdir build

$ cd build

$ cmake -D CMAKE_BUILD_TYPE=RELEASE \

-D CMAKE_INSTALL_PREFIX=/usr/local \

-D INSTALL_C_EXAMPLES=ON \

-D INSTALL_PYTHON_EXAMPLES=ON \

-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \

-D BUILD_EXAMPLES=ON ..


 11. 구성요소를 컴파일한 다음 자신의 환경에서 만든 OpenCV를 설치합니다.


$make -j4

$sudo make install

$sudo make ldconfig


 12. OpenCV 설치가 완료되면 이를 Python에서 사용할 수 있도록 Sym-link를 추가해 줍니다.


$ cd ~/.virtualenvs/cv/lib/python2.7/site-packages/

$ ln -s /usr/local/lib/python2.7/site-packages/cv2.so cv2.so


 13. 이로서 OpenCV의 설치가 완료되었습니다. cv2 라이브러리를 불러오는 것으로 실행을 확인해 봅니다.


>>> import cv2

>>> cv2.__version__



 위와 같이 자신이 설치한 OpenCV 버전이 나오면 설치는 성공한 것입니다! 이제 SIFT가 실행이 잘 되는지 확인해 보도록 합니다!


 아래 이미지에 대한 SIFT 연산을 수행하는 프로그램을 작성해 보겠습니다.



1
2
3
4
5
6
7
8
9
10
11
import cv2
import numpy as np
 
img = cv2.imread('elecs.png')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray,None)
 
cv2.drawKeypoints(gray,kp,img,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('sift_elecs.jpg',img)
cs


- 결과




 -참고자료

http://www.pyimagesearch.com/2015/06/22/install-opencv-3-0-and-python-2-7-on-ubuntu/

http://www.flowdas.com/blog/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-virtualenv/


300x250

File System 및 커널 수정을 gedit로 쉽게 하는 방법(sudo root 권한으로 gedit 실행)

공대생의 팁 2015. 11. 16. 00:16

 리눅스를 사용하는 여러분들께서 최상단 폴더인 root 파일을 수정하실 때 어떻게 하시는지요? 가장 쉬운 방법으로 vi가 있을 것입니다. GUI가 없는 server 버전의 리눅스에서는 vi만이 거의 유일한 editor 수단으로 활용되고 있다고 봐도 무방할 정도로 vi는 linux 사용자에게 있어 뗄레야 뗄 수 없는 프로그램이지요. 하지만 vi의 최대 단점으로 일일히 단축 명령어를 이용해야 하다 보니 초보자가 사용하기에는 직관적이지 못해 사용하기가 상당히 불편하다는 점이 있습니다.

 물론 GUI 환경의 Desktop 버전을 사용하는 분이시라면 gedit라는 vi보다는 매우 편한 편집기가 있어 상당히 애용하다시피 하는데 막상 gedit로 루트 상단에 있는 파일을 수정할 수 없다는 치명적인 단점이 있습니다. 이 녀석을 마치 sudo 권한으로 root 상태에서 작업을 수행할 수 있다면 참 편할텐데 말이지요...



 정말 다행이게도 gedit를 root 권한을 사용하여 파일을 수정할 수 있는 방법이 존재합니다. 바로 gksu 명령어를 사용하는 방법입니다! 일반적으로 Terminal에서 root 권한을 얻어서 실행되는 프로그램의 경우 sudo를 사용합니다만 gui를 기반으로 하는 프로그램의 경우 gksu를 사용하면 마치 sudo와 같이 root 권한을 부여하여 root 파일을 수정할 수 있도록 권한이 설정됩니다.


$ gksu gedit &


 위와 같은 명령어를 수행하면 gedit를 root 모드에서 수행하는 것이 가능하여 최상단 / 에 있는 파일들을 자유롭게 수정할 수 있게 됩니다!




300x250

Android Studio로 improt 한 후 컴파일 타겟 변경하기(failed to find target with hash string ...)

 최근 안드로이드 스튜디오로 건너온 이래로 차근차근 Eclipse에서 사용하던 project 들을 옮기고 있습니다. 그러던 중 몇몇 프로젝트의 경우 아래와 같은 에러가 발생하더군요.


Error : Cause : failed to find target with hash string 'android-15'


 이는 기존에 Eclipse 에서 사용하던 프로젝트가 Android Studio로 건너왔을 때 해당 버전에서 설정한 컴파일 sdk 버전이 없을 경우 위와 같은 에러가 발생합니다.



 해결 방법으로는 2가지의 경우가 있습니다.

1. 해당 Target에 해당하는 안드로이드 버전을 SDK Manager를 실행하여 다운로드 받는다.

2. 컴파일 버전을 자신의 SDK Manager가 가지고 있는 버전으로 변경합니다. 변경 방법은 아래와 같습니다.


자신의 프로젝트 폴더 -> app -> build.gradle


 해당 Gradle에서 compileSdkVersion을 변경해주면 프로젝트가 정상적으로 동작됨을 확인하실 수 있습니다.



300x250

우분투 커널 업데이트 후 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