- ResultReceiver를 더 자세히 이해하기 위해서는 안드로이드 IPC 자료를 찾아볼 것.
- ResultReceiver 클래스는 Parcelable 인터페이스를 구현하므로 Parcelable 객체를 전달 받을 수 있는 모든 곳에서 콜백을 처리할 수 있다.
1. ResultReceiver 기본코드
- ResultReceiver 콜백
ResultReceiver resultReceiver = new ResultReceiver(textView.getHandler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
// 콜백
if (resultCode == RESULT_OK && resultData != null) {
String text = resultData.getString("message");
textView.setText(text);
}
}
};
- ResultReceiver 콜백 파라미터
BlankFragment fragment = new BlankFragment();
Bundle args = new Bundle();
args.putParcelable(ResultReceiver.class.getSimpleName(), resultReceiver);
fragment.setArguments(args);
또는
Intent intent = new Intent(getBaseContext(), SubActivity.class);
intent.putExtra(ResultReceiver.class.getSimpleName(), resultReceiver);
startActivity(intent);
> ResultReceiver가 Parcelable를 구현하므로 Parcelable를 수신할 수 있는 모든 곳에서 콜백을 동작시킬 수 있다.
> 주로 Activity와 Service 간 통신에 사용된다.
- Bundle 전송
ResultReceiver resultReceiver = getArguments().getParcelable(ResultReceiver.class.getSimpleName());
Bundle bundle = new Bundle();
bundle.putString("message", "Hello, World!");
resultReceiver.send(Activity.RESULT_OK, bundle);
> sned를 통해 Bundle를 전송하면 onReceiveResult 메소드에서 수신한다.
2. 샘플코드
소스코드
APK
2019년 3월 12일 화요일
안드로이드 관리자 권한 예제 - DevicePolicyManager
- 관리자 권한 취득
- 카메라 사용 제한하기
- 앱 삭제 제한하기(어플리케이션 관리 화면에서는 삭제 가능)
1. 관리자 권한
- xml 정의 - device_admin_receiver.xml
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<disable-camera />
</uses-policies>
</device-admin>
> res 디렉토리의 xml 디렉토리에 xml 문서 생성
> 카메라 제어를 위해 <disable-camera /> 적용
> 레퍼런스 :
https://developer.android.com/guide/topics/admin/device-admin
> 안드로이드 9 버전 이후 부터 변경 사항이 있습니다.
https://developers.google.com/android/work/device-admin-deprecation
- DeviceAdminReceiver 상속
public class AppDeviceAdminReceiver extends DeviceAdminReceiver {
private static final String TAG = AppDeviceAdminReceiver.class.getSimpleName();
@Override
public void onEnabled(Context context, Intent intent) {
super.onEnabled(context, intent);
Log.d(TAG, "Admin onEnabled");
}
@Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
Log.d(TAG, "Admin onDisabled");
}
}
- 리시버 등록 - AndroidManifest.xml
- 관리자 권한 요청
ComponentName componentName = new ComponentName(this, AppDeviceAdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
startActivityForResult(intent, DEVICE_ADMIN_ADD_RESULT_ENABLE);
> 권한 확인
final boolean adminActive = devicePolicyManager.isAdminActive(componentName);
> 카메라 제어 확인
boolean cameraDisabled = devicePolicyManager.getCameraDisabled(componentName);
2. 샘플코드
소스코드
APK
- 카메라 사용 제한하기
- 앱 삭제 제한하기(어플리케이션 관리 화면에서는 삭제 가능)
1. 관리자 권한
- xml 정의 - device_admin_receiver.xml
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<disable-camera />
</uses-policies>
</device-admin>
> res 디렉토리의 xml 디렉토리에 xml 문서 생성
> 카메라 제어를 위해 <disable-camera /> 적용
> 레퍼런스 :
https://developer.android.com/guide/topics/admin/device-admin
> 안드로이드 9 버전 이후 부터 변경 사항이 있습니다.
https://developers.google.com/android/work/device-admin-deprecation
- DeviceAdminReceiver 상속
public class AppDeviceAdminReceiver extends DeviceAdminReceiver {
private static final String TAG = AppDeviceAdminReceiver.class.getSimpleName();
@Override
public void onEnabled(Context context, Intent intent) {
super.onEnabled(context, intent);
Log.d(TAG, "Admin onEnabled");
}
@Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
Log.d(TAG, "Admin onDisabled");
}
}
- 리시버 등록 - AndroidManifest.xml
<receiver
android:name=".AppDeviceAdminReceiver"
android:description="@string/device_admin_description"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_receiver" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
ComponentName componentName = new ComponentName(this, AppDeviceAdminReceiver.class);
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
startActivityForResult(intent, DEVICE_ADMIN_ADD_RESULT_ENABLE);
> 권한 확인
final boolean adminActive = devicePolicyManager.isAdminActive(componentName);
> 카메라 제어 확인
boolean cameraDisabled = devicePolicyManager.getCameraDisabled(componentName);
2. 샘플코드
소스코드
APK
라벨:
관리자 권한,
안드로이드,
카메라 제어,
DevicePolicyManager
위치:
대한민국
2019년 3월 8일 금요일
Room 아키텍처 예제
- 아키텍처 구조
- 구글 코드랩 예제 :
https://codelabs.developers.google.com/codelabs/android-room-with-a-view/index.html?index=..%2F..index#0
1. 기본 구성
- dependencies 구성
def room_version = "2.1.0-alpha04"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
def lifecycle_version = "2.0.0"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
> 라이프사이클
https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ko#declaring_dependencies
> Room
https://developer.android.com/jetpack/androidx/releases/room?hl=ko
- Entity
@Entity(tableName = "user_table")
public class User {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int id;
@NonNull
@ColumnInfo(name = "userName")
private String userName;
@NonNull
@ColumnInfo(name = "age")
private int age;
}
> autoGenerate를 적용하면 insert 과정에서 id 값이 자동으로 증가한다.
- Dao
@Dao
public interface UserDao {
@Insert
long insert(User user);
@Update
int update(User user);
@Query("DELETE FROM user_table")
int deleteAll();
@Query("DELETE FROM user_table WHERE id = :id")
int deleteUser(int id);
@Query("SELECT * from user_table ORDER BY userName ASC")
LiveData<List<User>> getAllUsers();
}
> LiveData를 사용하지 않을 경우
@Query("SELECT * from user_table ORDER BY userName ASC")
List<User> getAllUsers();
- Database
@Database(entities = {User.class}, version = 1)
public abstract class UserRoomDatabase extends RoomDatabase {
public abstract UserDao userDao();
private static volatile UserRoomDatabase INSTANCE;
static UserRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (UserRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), UserRoomDatabase.class, "user_database").build();
}
}
}
return INSTANCE;
}
}
> AndroidViewModel를 상속하고 대부분의 메소드들은 델리게이트로 구성한다.
- ViewModel 구현
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.getAllUsers().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
}
});
> 라이프사이클을 이용해서 ViewModel을 통해 DB 연동을 한다.
> 라이프 사이클 :
https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ko#declaring_dependencies
3. 샘플코드
소스코드
APK
- Room의 구성을 더 강력하게 만드는 구성은 Room + ViewModel + Paging 조합이다.
추가적으로 Data Binding을 함께 구성하기도 하지만 반드시 필요한 경우만 사용해하 한다.
- Room을 사용하는 주요 목적은 안드로이드 앱 아키텍처 구조 적용과 SQLiteOpenHelper의 불편함을 줄이기 위함이다.
- 안드로이드와 SQLite의 관계를 이해하고 Room 아키텍처를 사용하도록 하자.
- 구글 코드랩 예제 :
https://codelabs.developers.google.com/codelabs/android-room-with-a-view/index.html?index=..%2F..index#0
1. 기본 구성
- dependencies 구성
def room_version = "2.1.0-alpha04"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
def lifecycle_version = "2.0.0"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
> 라이프사이클
https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ko#declaring_dependencies
> Room
https://developer.android.com/jetpack/androidx/releases/room?hl=ko
- Entity
@Entity(tableName = "user_table")
public class User {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
private int id;
@NonNull
@ColumnInfo(name = "userName")
private String userName;
@NonNull
@ColumnInfo(name = "age")
private int age;
}
> autoGenerate를 적용하면 insert 과정에서 id 값이 자동으로 증가한다.
- Dao
@Dao
public interface UserDao {
@Insert
long insert(User user);
@Update
int update(User user);
@Query("DELETE FROM user_table")
int deleteAll();
@Query("DELETE FROM user_table WHERE id = :id")
int deleteUser(int id);
@Query("SELECT * from user_table ORDER BY userName ASC")
LiveData<List<User>> getAllUsers();
}
> LiveData를 사용하지 않을 경우
@Query("SELECT * from user_table ORDER BY userName ASC")
List<User> getAllUsers();
- Database
@Database(entities = {User.class}, version = 1)
public abstract class UserRoomDatabase extends RoomDatabase {
public abstract UserDao userDao();
private static volatile UserRoomDatabase INSTANCE;
static UserRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (UserRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), UserRoomDatabase.class, "user_database").build();
}
}
}
return INSTANCE;
}
}
- 설명
androidx.room:room-compiler가 generatedJava 디렉토리의 소스코드를 자동 생성한다.
SQLiteOpenHelper를 사용했을 때 보다 더 생산성이 좋다.
링크 :
2. 안드로이드 앱 아키텍처 적용
Room 아키텍처는 안드로이드 앱 아키텍처의 DB 연동 구성요소이다.
- Repository
class UserRepository {
private static final String TAG = UserRepository.class.getSimpleName();
private final UserDao userDao;
private final LiveData<List<User>> allUsers;
UserRepository(Application application) {
UserRoomDatabase db = UserRoomDatabase.getDatabase(application);
userDao = db.userDao();
allUsers = userDao.getAllUsers();
}
public void insert(User user) {
new AsyncTask<User, Void, Long>() {
@Override
protected Long doInBackground(User... users) {
if (userDao == null)
return -1L;
return userDao.insert(users[0]);
}
@Override
protected void onPostExecute(Long aLong) {
super.onPostExecute(aLong);
Log.d(TAG, "insert : " + aLong);
}
}.execute(user);
}
public void update(User user) {
new AsyncTask<User, Void, Integer>() {
@Override
protected Integer doInBackground(User... users) {
if (userDao == null)
return -1;
return userDao.update(users[0]);
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
Log.d(TAG, "update : " + integer);
}
}.execute(user);
}
public void deleteAll() {
new AsyncTask<Void, Void, Integer>() {
@Override
protected Integer doInBackground(Void... voids) {
if (userDao == null)
return -1;
return userDao.deleteAll();
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
Log.d(TAG, "deleteAll : " + integer);
}
}.execute();
}
public void deleteUser(int id) {
new AsyncTask<Integer, Void, Integer>() {
@Override
protected Integer doInBackground(Integer... integers) {
if (userDao == null)
return -1;
return userDao.deleteUser(integers[0]);
}
@Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
Log.d(TAG, "deleteUser : " + integer);
}
}.execute(id);
}
public LiveData<List<User>> getAllUsers() {
return allUsers;
}
}
> 메인쓰레드에서 DB 연동을 사용하지 않아야 한다.
> LiveData를 사용하지 않는 곳은 AsyncTask를 적용한다.
- AndroidViewModel
public class UserViewModel extends AndroidViewModel {
private static final String TAG = UserViewModel.class.getSimpleName();
private final UserRepository repository;
private final LiveData<List<User>> allUsers;
public UserViewModel(Application application) {
super(application);
repository = new UserRepository(application);
allUsers = repository.getAllUsers();
}
public void insert(User user) {
repository.insert(user);
}
public void update(User user) {
repository.update(user);
}
public void deleteAll() {
repository.deleteAll();
}
public void deleteUser(int id) {
repository.deleteUser(id);
}
public LiveData<List<User>> getAllUsers() {
return allUsers;
}
}
> AndroidViewModel를 상속하고 대부분의 메소드들은 델리게이트로 구성한다.
- ViewModel 구현
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.getAllUsers().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
}
});
> 라이프사이클을 이용해서 ViewModel을 통해 DB 연동을 한다.
> 라이프 사이클 :
https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ko#declaring_dependencies
3. 샘플코드
소스코드
APK
- Room의 구성을 더 강력하게 만드는 구성은 Room + ViewModel + Paging 조합이다.
추가적으로 Data Binding을 함께 구성하기도 하지만 반드시 필요한 경우만 사용해하 한다.
- Room을 사용하는 주요 목적은 안드로이드 앱 아키텍처 구조 적용과 SQLiteOpenHelper의 불편함을 줄이기 위함이다.
- 안드로이드와 SQLite의 관계를 이해하고 Room 아키텍처를 사용하도록 하자.
동기화 예제 - synchronized
- 자바 동기화(synchronized) 기본 예
1. 문제가 되는 코드
- 기본 코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 13312
Thread 1 : 89300
balance : -1000
count total : 102612
> 쓰레드1과 쓰레드2가 동일한 시간에 balance 값이 1000 보다 큰 경우만 -1000을 하면 결과적으로 1000 > 0 > -1000이 되는 문제가 발생한다.
> 루프 카운트도 100000000 / 1000 번을 하는 것이 아닌 것이 확인된다.
2. synchronized 적용
- 기본코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 0
Thread 1 : 100000
balance : 0
count total : 100000
> 쓰레드2는 쓰레드1이 simpleSynchronized 객체를 동기화 하기 때문에 쓰레드1의 작업이 완료되기 전까지 대기 한다.
> synchronized는 동기가 필요한 곳에 적절하게 적용해야 한다.
> 주된 예로 다중쓰레드 환경에서 Map 객체의 put과 remove를 synchronized없이 처리하면 문제가 되는 경우가 있다.
3. 동기화 기본 문법
- 객체 동기화
Object object = new Object();
synchronized (object) {
}
synchronized (this) {
}
> 기본변수(int, long, double 등) 타입은 적용 불가.
- 클래스 단위의 동기화
synchronized (Object.class) {
}
- 메소드 동기화
public synchronized void setObject(Object object) {
}
1. 문제가 되는 코드
- 기본 코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 13312
Thread 1 : 89300
balance : -1000
count total : 102612
> 쓰레드1과 쓰레드2가 동일한 시간에 balance 값이 1000 보다 큰 경우만 -1000을 하면 결과적으로 1000 > 0 > -1000이 되는 문제가 발생한다.
> 루프 카운트도 100000000 / 1000 번을 하는 것이 아닌 것이 확인된다.
2. synchronized 적용
- 기본코드
public class SimpleSynchronized {
int balance = 100000000;
int count1 = 0;
int count2 = 0;
public int getBalance() {
return balance;
}
public void addBalance(int balance) {
this.balance += balance;
}
public static void main(String[] args) {
final SimpleSynchronized simpleSynchronized = new SimpleSynchronized();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count1++;
}
}
System.out.println("Thread 1 : " + simpleSynchronized.count1);
}
}.start();
new Thread() {
@Override
public void run() {
synchronized (simpleSynchronized) {
while (simpleSynchronized.getBalance() >= 1000) {
simpleSynchronized.addBalance(-1000);
simpleSynchronized.count2++;
}
System.out.println("Thread 2 : " + simpleSynchronized.count2);
}
}
}.start();
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("balance : " + simpleSynchronized.balance);
System.out.println("count total : " + (simpleSynchronized.count1 + simpleSynchronized.count2));
}
}.start();
}
}
- 결과
Thread 2 : 0
Thread 1 : 100000
balance : 0
count total : 100000
> 쓰레드2는 쓰레드1이 simpleSynchronized 객체를 동기화 하기 때문에 쓰레드1의 작업이 완료되기 전까지 대기 한다.
> synchronized는 동기가 필요한 곳에 적절하게 적용해야 한다.
> 주된 예로 다중쓰레드 환경에서 Map 객체의 put과 remove를 synchronized없이 처리하면 문제가 되는 경우가 있다.
3. 동기화 기본 문법
- 객체 동기화
Object object = new Object();
synchronized (object) {
}
synchronized (this) {
}
> 기본변수(int, long, double 등) 타입은 적용 불가.
- 클래스 단위의 동기화
synchronized (Object.class) {
}
- 메소드 동기화
public synchronized void setObject(Object object) {
}
라벨:
동기화,
자바,
Java,
synchronized
위치:
대한민국
Restful API 예제코드 - HttpURLConnection
1. Restful API - HttpURLConnection
- 기본코드
String urlStr = "https://www.instagram.com/web/search/topsearch/?context=blended&query=java";
URL url = null;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
url = new URL(urlStr);
connection = urlStr.startsWith("https://") ? (HttpsURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("cache-control", "no-cache");
connection.connect();
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
StringBuffer buffer = null;
if (code == HttpURLConnection.HTTP_OK) {
buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String temp = null;
while ((temp = reader.readLine()) != null) {
buffer.append(temp);
}
reader.close();
}
connection.disconnect();
System.out.println(String.format("Response : %d, %s", code, message));
System.out.println("Response DATA : ");
System.out.println(buffer == null ? "NULL " : buffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 결과
Response : 200, OK
Response DATA :
{}
> URL 문자열에서 HTTPS를 판단해서 캐스팅 할 클래스를 선택
> Restful API 사양에 맞는 RequestHeader 설정
> 예제코드에서 사용한 Restful API 주소는 인스타그램 검색 API
- 기본코드
String urlStr = "https://www.instagram.com/web/search/topsearch/?context=blended&query=java";
URL url = null;
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
url = new URL(urlStr);
connection = urlStr.startsWith("https://") ? (HttpsURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
connection.setRequestProperty("cache-control", "no-cache");
connection.connect();
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
StringBuffer buffer = null;
if (code == HttpURLConnection.HTTP_OK) {
buffer = new StringBuffer();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String temp = null;
while ((temp = reader.readLine()) != null) {
buffer.append(temp);
}
reader.close();
}
connection.disconnect();
System.out.println(String.format("Response : %d, %s", code, message));
System.out.println("Response DATA : ");
System.out.println(buffer == null ? "NULL " : buffer.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 결과
Response : 200, OK
Response DATA :
{}
> URL 문자열에서 HTTPS를 판단해서 캐스팅 할 클래스를 선택
> Restful API 사양에 맞는 RequestHeader 설정
> 예제코드에서 사용한 Restful API 주소는 인스타그램 검색 API
라벨:
자바,
HttpURLConnection,
Java,
RestAPI,
Restful API
위치:
대한민국
2019년 3월 6일 수요일
칼만필터 예제
1. 기본코드
public class Kalman {
private static final double Q = 0.00001;
private static final double R = 0.001;
private double P = 1;
private double X = 0;
private double K;
public Kalman(double value) {
X = value;
}
// 계산
private void measurementUpdate() {
K = (P + Q) / (P + Q + R);
P = R * (P + Q) / (P + Q + R);
}
// 현재값을 받아 계산된 공식을 적용하고 반환한다
public double update(double measurement) {
measurementUpdate();
X = X + (measurement - X) * K;
return X;
}
}
- 상수 Q와 R의 이해가 필요
- 주 사용처 : 센서(온도, 습도, 자기장, 가속도계), RSSI 시그널 등의 오차 계산
- 칼만필터 위키백과 :
https://ko.wikipedia.org/wiki/%EC%B9%BC%EB%A7%8C_%ED%95%84%ED%84%B0
public class Kalman {
private static final double Q = 0.00001;
private static final double R = 0.001;
private double P = 1;
private double X = 0;
private double K;
public Kalman(double value) {
X = value;
}
// 계산
private void measurementUpdate() {
K = (P + Q) / (P + Q + R);
P = R * (P + Q) / (P + Q + R);
}
// 현재값을 받아 계산된 공식을 적용하고 반환한다
public double update(double measurement) {
measurementUpdate();
X = X + (measurement - X) * K;
return X;
}
}
- 상수 Q와 R의 이해가 필요
- 주 사용처 : 센서(온도, 습도, 자기장, 가속도계), RSSI 시그널 등의 오차 계산
- 칼만필터 위키백과 :
https://ko.wikipedia.org/wiki/%EC%B9%BC%EB%A7%8C_%ED%95%84%ED%84%B0
2019년 3월 5일 화요일
외부 프로세스 실행하기 - 자바
1. 프로세스 실행 - Process
- 메모장 실행 코드
try {
String command = "notepad";
Process process = Runtime.getRuntime().exec(command);
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
- 결과
메모장 프로세스가 호출되면 process.waitFor(); 메소드에서 대기.
메모장 프로세스가 종료되면 process.destroy(); 메소드를 호출하고 종료.
2. 프로세스 출력 가져오기
- 실행코드
try {
String command = "cmd";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "949"));
String temp = null;
while ((temp = reader.readLine()) != null) {
System.out.println(temp);
}
reader.close();
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
- 결과
cmd는 출력 후 종료되는 방식이 아니므로 process.waitFor(); 메소드에서 대기.
keytool 실행 프로세스를 이용해서 테스트 해보면 process.destroy(); 까지 정상적으로 실행됩니다.
라벨:
외부 프로세스 실행,
자바,
Java,
Process,
Runtime 실행
위치:
대한민국
피드 구독하기:
글 (Atom)