Nano Blog - 오병우

안드로이드 스튜디오 4.0.1까지는 잘 작동했는데 4.1로 업그레이드하니 Layout XML에서 지정한 id를 Kotlin (.kt) 파일에서 바로 참조할 수 없고 findViewById<클래스>(R.id.아이디)로 참조해야 한다.

안드로이드 4.2에서 View Binding을 사용하도록 변경될 것이라고 하는데 그 사이에 기존에 사용하던 코드를 사용할 수 있는 방법을 설명한다.

 

1. build.gradle (Module: ~.app) 파일 앞 부분에 'kotlin-android-extensions' 추가

(Before) -------------------------------------

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

(After) -------------------------------------

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

 

2. 화면 오른쪽 위 Sync Now 클릭

 

하루가 다르게 변하고 점점 복잡해지는 안드로이드 개발 환경에 대한 피로도가 높아진다.

 

Android Studio에서 Tools 메뉴-SDK Manager-SDK Tools Tab 열기

 

Android Emulator Hypervisor Driver for AMD Processors (installer) 체크

OK 버튼

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

제어판-프로그램-프로그램 및 기능-Windows 기능 켜기/끄기

 

다음 두 개 기능 켜기 (체크)

1. Windows 하이퍼바이저 플랫폼

2. 가상 머신 플랫폼

 

그 뒤에 AVD 실행하면 x86 CPU 이미지도 실행 가능

Kotlin으로 Volley NetworkImageView 사용하려고 공식 문서를 따라하는데 에러가 발생한다.


https://developer.android.com/training/volley/requestqueue#kotlin


원인은 Kotlin의 Null safety 때문.

다음의 코드로 해결할 수 있다.

mImageLoader = ImageLoader(mQueue,
object : ImageLoader.ImageCache {
private val cache = LruCache<String, Bitmap>(20)

override fun getBitmap(url: String): Bitmap? {
return cache.get(url)
}

override fun putBitmap(url: String, bitmap: Bitmap) {
cache.put(url, bitmap)
}
})

차이점은 getBitmap()의 return type을 Nullable인 Bitmap?으로 변경함

물음표 하나로 해결됨


Kotlin에 익숙하면 금방 고칠 수 있겠지만... 공식 문서인데...


iOS 처럼 개발자를 위해 예제 좀 바로 가져다 쓰도록 잘 만들어 줬으면 좋겠다. 운영체제 옆그레이드에만 열을 올리는 듯...


실습 중에 R에 빨간색으로 표시되는 에러로 고생하는 학생이 많다.

class R은 Resource를 관리하기 위해 자동으로 생성되는 클래스이다.

XML을 추가했는데 오타가 있거나 하면 R 클래스가 제대로 생성되지 않는다. 일단 최근에 추가한 내용에 오타가 없는지 확인이 필요하다.


간혹 오류가 없는데도 R이 제대로 생성되지 않는 경우가 있다.

메뉴 Build-Rebuild Project를 수행하거나 Android Studio를 다시 시작해 보면 해결되는 경우가 있다.


메뉴 File-Invalidate Cashes/Restart로 해결되는 경우도 있다.


이클립스 사용할 때 Ctrl+Shift+O를 애용했는데 안드로이드 스튜디오는 매번 Alt+Enter 눌러줘야 되서 불편하다.


Auto Import 기능을 사용하면 편리해 진다.


File-settings-Editor-General-Auto Import


Ask를 All로 변경.

Add unambiguous ... 체크

Optimize ... 체크

BitmapDrawable d = (BitmapDrawable)getResources().getDrawable(R.drawable.img, null); // , null 추가


build.gradle에서 minSdkVersion 21로 변경

마시멜로부터 드디어 Android에서 공식 MIDI API를 제공한다. iOS에 비해 너무 늦다.


공식 API 설명

http://developer.android.com/intl/ko/reference/android/media/midi/package-summary.html


MIDI 노트 재생하는 소소를 원하면 다음의 샘플 참조.

http://developer.android.com/intl/ko/samples/MidiSynth/index.html


미디 디바이스와 연결 관련 내용은 다음의 링크 참조.


http://developer.android.com/intl/ko/samples/MidiScope/index.html


비록 MIDITools라는 라이브러리를 사용하긴 하지만 MIDIKeyboard는 봐둘 필요가 있을 듯 하다. 이 분이 아마도 Android MIDI API 개발에 참여하신듯...(잘 모름)

https://github.com/philburk/android-midisuite



1. Volley 사용 (권장)


http://developer.android.com/intl/ko/training/volley/index.html




2. build.gradle에 apache 라이브러리 사용 추가 (권장하지 않음. 임시로 돌릴 때만 사용할 것)


android {
compileSdkVersion 23
buildToolsVersion "23.0.1"

defaultConfig {
...
}
buildTypes {
...
}
    useLibrary 'org.apache.http.legacy'
}


왼쪽 위 삼선 눌러서 DrawerLayout 나올 때 원래 내용(나머지 부분)이 어두워 지는 것을 막는 방법

mDrawerLayout.setScrimColor(Color.TRANSPARENT);


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

그냥 그림자 없애려면 다음 함수 사용


setDrawerShadow(Drawable shadowDrawable, int gravity)

setDrawerShadow(int resId, int gravity)

모바일 융합 기술 센터

스마트 앱 창작터 안드로이드 기초 및 실습

 

Day9Ex1 앞부분 구현 내용 (내용 추가 필요)

 

package kr.re.mctc.android.day9ex1weatherinfo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Window;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

 String mResult = null;
 WeatherTask mTask = null;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  // setContentView() 앞에서 호출
  requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

  setContentView(R.layout.activity_main);
  
  mTask = new WeatherTask();
  mTask.execute();
 }

 class WeatherTask extends AsyncTask<Void, Void, String> {
  @Override
  protected void onPreExecute() {
   super.onPreExecute();
   setProgressBarIndeterminate(true);
  }

  @Override
  protected String doInBackground(Void... params) {
   String query = "http://api.openweathermap.org/data/2.5/weather?q=kumi";
   BufferedReader rd = null;
   String rLine = "";
   StringBuilder result = new StringBuilder();
   
   HttpClient httpClient = new DefaultHttpClient();
   HttpGet httpGet = new HttpGet(query);
   try {
    HttpResponse response = httpClient.execute(httpGet);
   
    rd = new BufferedReader(new InputStreamReader(
       response.getEntity().getContent()));
    while ((rLine = rd.readLine()) != null) {
     result.append(rLine);
    }
    return result.toString();
   } catch (ClientProtocolException e) {
    e.printStackTrace();
   } catch (IOException e) {
    e.printStackTrace();
   }
   return null;
  }
  
  @Override
  protected void onPostExecute(String result) {
   super.onPostExecute(result);
   setProgressBarIndeterminate(false);
   
   Toast.makeText(MainActivity.this,
     result, Toast.LENGTH_SHORT).show();
   
   mResult = result;
  }  
 }
}

모바일 융합 기술 센터

스마트 앱 창작터 안드로이드 기초 및 실습 강의 자료

Day8Ex2MyList - MainActivity.java

 

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity
       implements OnItemClickListener {

// protected String[] mArray = { "걸스데이", "에이핑크", "소녀시대", "시크릿",
//   "걸스데이", "에이핑크", "소녀시대", "시크릿",
//   "걸스데이", "에이핑크", "소녀시대", "시크릿",
//   "걸스데이", "에이핑크", "소녀시대", "시크릿" };
 ArrayList<IdolInfo> mArray = new ArrayList<IdolInfo>();
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  mArray.add(new IdolInfo("걸스데이", "썸씽"));
  mArray.add(new IdolInfo("에이핑크", "No No No"));
  mArray.add(new IdolInfo("소녀시대", "Gee"));
  mArray.add(new IdolInfo("시크릿", "매직"));
  mArray.add(new IdolInfo("걸스데이", "썸씽"));
  mArray.add(new IdolInfo("에이핑크", "No No No"));
  mArray.add(new IdolInfo("소녀시대", "Gee"));
  mArray.add(new IdolInfo("시크릿", "매직"));
  
  ListView list = (ListView)findViewById(R.id.listView);
//  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
//        android.R.layout.simple_list_item_1,
//        mArray);
  IdolAdapter adapter = new IdolAdapter(this,
    android.R.layout.simple_list_item_1);
  list.setAdapter(adapter);
  list.setOnItemClickListener(this);
 }

 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1,
   int position,
   long arg3) {
//  Toast.makeText(this, "클릭: " + position + "(" + mArray[position] + ")",
//      Toast.LENGTH_SHORT).show();
  new AlertDialog.Builder(this)
  .setTitle("아이템 선택")
  .setMessage(mArray.get(position).getName() + " 아이템을 선택했습니다.")
  .setPositiveButton("확인", null)
  .show();
 }
 
 public class IdolInfo {
  protected String name;
  protected String song;
  
  public IdolInfo(String name, String song) {
   super();
   this.name = name;
   this.song = song;
  }

  public String getName() {
   return name;
  }

  public void setName(String name) {
   this.name = name;
  }

  public String getSong() {
   return song;
  }

  public void setSong(String song) {
   this.song = song;
  }
 }
 
 static class IdolViewHolder {
  TextView idolName;
 }
 
 public class IdolAdapter extends ArrayAdapter<IdolInfo> {

  protected LayoutInflater mInflater = null;
  
  public IdolAdapter(Context context, int resource) {
   super(context, resource);
   mInflater = LayoutInflater.from(context);
  }

  @Override
  public int getCount() {
   return mArray.size();
  }

  @Override
  public View getView(int position, View v, ViewGroup parent) {
   IdolViewHolder viewHolder;
   if (v == null) {
    v = mInflater.inflate(android.R.layout.simple_list_item_1,
         parent, false);
    
    viewHolder = new IdolViewHolder();
    viewHolder.idolName = (TextView)v.findViewById(android.R.id.text1);
    v.setTag(viewHolder);
   }
   else {
    viewHolder = (IdolViewHolder)v.getTag();
   }
   
   IdolInfo info = mArray.get(position);
   if (info != null) {
    viewHolder.idolName.setText(info.getName());
   }
   
   return v;
  }
 }
}

안드로이드도 BLE를 제공하네요. 


'프로그래밍 > Android 프로그래밍' 카테고리의 다른 글

[Android] AsyncTask 예제  (0) 2014.08.14
[Android] List 예제  (0) 2014.08.13
[Android] MIDI 프로그래밍  (1) 2014.06.24
[Android] Music Synthesizer  (0) 2014.06.24
[Android] Serial 통신 (RS-232C)  (0) 2014.06.12

[Update] 2015년의 Android API23 Marshmallow에서 MIDI API를 제공하고 있으므로 MIDI Device에 연결하거나 노트를 재생하시려는 분들에게 이 글은 큰 의미가 없을 것 같습니다. 

대신 최신 블로그 글을 참조해 주십시오.

http://bwoh.tistory.com/89


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

실제로 미디를 사용한 프로그램(시퀀서, 건반, 기타 등 음악 앱이나 게임 앱)을 만들기 위해서는 JetPlayer가 답으로 생각된다.


C:\adt-bundle-windows-x86_64-20140321\sdk\platforms\android-3\samples\JetBoy


ADT (Android Developer Tools) 깔고 나서 sdk 디렉토리에 보면 JetBoy라는 JetPlayer를 사용하는 샘플 앱이 있다. (밑줄 친 앞부분은 버전과 각자 설치 환경에 따라 달라질 수 있음)


이걸 분석해 보면 JetPlayer를 사용할 수 있을 듯...


다음 디렉토리에 있는 JetCreator를 사용하여 MIDI 노트를 사용하는 JET 파일을 만들고 그 파일을 앱에서 활용한다.


C:\adt-bundle-windows-x86_64-20140321\sdk\tools\Jet


JetCreator를 사용하려면 Python을 깔아야 한다.



Android 공식 API Guide는 아래 링크로...


http://developer.android.com/guide/topics/media/jetplayer.html



코드 내에서 MIDI 노트를 바로 플레이할 수 있는 기능이 있는지 모르겠다. 아시는 분은 댓글 달아 주시길...



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


MIDI File 생성

http://kevinboone.net/javamidi.html


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


Java Sound FAQ

http://www.jsresources.org/faq_midi.html


Java Sound API

http://docs.oracle.com/javase/1.5.0/docs/guide/sound/programmer_guide/


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


CodeGuru에서 MIDI 검색 (Windows용 MCI or DirectX 사용)


http://www.codeguru.com/vb/gen/vb_multimedia/article.php/c1097/Advanced-MIDI-Programming--Utility.htm

http://www.codeguru.com/cpp/g-m/multimedia/article.php/c1573/Playing-MIDI-Files-Directly-From-The-Resource.htm

http://www.codeguru.com/cpp/g-m/multimedia/audio/article.php/c4715/Creating-an-MCI-MIDI-Class.htm

Music Synthesizer for Android


https://code.google.com/p/music-synthesizer-for-android/


안드로이드에서는 iOS에 비해 사운드 처리가 빈약해 보인다.

Midi 프로그래밍을 찾다보니 복잡하지만 좋아보이는 코드가 있었다. 얼핏 보면 NDK도 사용하고 있는 것으로 보인다.


apk 파일이 있으니 받아서 실행해 보시길...


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


JetPlayer를 사용해서 미디 파일을 출력하는 것이 그나마 가장 쉬운 방법으로 보인다.

OpenSL을 사용하는 방법이 가장 latency를 줄일 수 있는 방법이라고 한다.


mini2440에서 시리얼 통신이 필요해서 찾아 보는 중임...


https://code.google.com/p/android-serialport-api/

https://code.google.com/p/android-serialport-api/wiki/android_to_rs232_guideline?tm=6



http://android-serialport-api.googlecode.com/svn/trunk/

http://android-serialport-api.googlecode.com/svn/trunk/android-serialport-api/project/



http://www.xue5.com/Mobile/Mobile/678712.html


https://github.com/roboguice/roboguice


https://github.com/excilys/androidannotations


Roboguice (로보주스) 동영상: http://www.youtube.com/watch?v=-npv20gWftc

Android Annotations 동영상: http://www.parleys.com/play/5148922b0364bc17fc56c96d/chapter1/about


살펴 보시기 바랍니다~


곧 나온다고 하네요~


하드웨어는 6월에 나온다는 것 같군요...


http://developer.android.com/wear/index.html