'3. Implementation/Android'에 해당되는 글 51건
- 2011.07.28 시스템 서비스에 접근하기
- 2011.07.21 apk 및 .jar 파일을 재수정하여 패키징하는 방법
- 2011.07.21 실행중인 Task 리스트 얻기
- 2011.07.19 [펌] 하나의 프로세스에서 여러 애플리케이션 실행하기
- 2011.07.19 [펌] 안드로이드 소스 빌드시 일부만 빌드하기 - mmm 명령
- 2011.06.16 Android 프레임워크에서 사용하는 uid 의 종류
- 2011.03.25 ADB 디버깅 로그
- 2011.03.09 성능 벤치마킹 App
- 2011.03.07 How to discover memory usage of my application in Android
- 2011.02.21 stdout 와 stderr 출력 보기
- 2011.02.21 Wireless Adb Debugging (TCP 를 이용한 adb 디버깅) - Rooting Only 3
- 2011.02.21 안드로이드 CPU Usage & Memory Usage 가져오기
- 2011.02.14 Droid Explorer
- 2011.02.10 Security Permissions in Android
- 2011.01.27 Gingerbread NDK Awesomeness
- 2010.12.08 실행가능한 애플리케이션 목록 가져오기
- 2010.10.09 [펌] 소스 #3 - Dialog 없이 wheel 만 있는 ProgressBar 만들고 WebView 위에서 사용하기
- 2010.08.16 Local Service and Remote Service ( AIDL Service ) 3
- 2010.08.15 HttpClient 및 URL 테스트
- 2010.08.15 ContentProvider Example
시스템 서비스에 접근하기
android.os.IServiceManager sm = android.os.ServiceManagerNative.getDefault(); try { String[] services = sm.listServices(); for (int i = 0; i < services.length; i++) { Log.i("Services", i + " : " + services[i]); } } catch (DeadObjectException e) { Log.i("Services", e.getMessage(), e); }아래는 애플리케이션에서 이용가능한 API 목록입니다. 단, 인터페이스에 접근할 수 있다고 해서 사용가능한 거랑은 다릅니다. 왜냐면 적절한 권한이 요구될 수 있기 때문입니다.
또한 출처 워낙 글이 옛날(2007. 12. 14)꺼라 인터페이스 이름이 변경된 서비스들이 있을 수 있습니다.
Window
android.view.IWindowManager windowServicePackage
= android.view.IWindowManager.Stub.asInterface(sm.getService("window"));
android.content.IPackageManager packageService= android.content.IPackageManager.Stub.asInterface(sm.getService("package"));
Power
android.os.IPowerManager powerService
= android.os.IPowerManager.Stub.asInterface(sm.getService("power"));
Statistics
android.os.IStatisticsService statisticsService= android.os.IStatisticsService.Stub.asInterface(sm.getService("statistics"));
Activity
android.app.IActivityManager activityService= android.app.IActivityManager.Stub.asInterface(sm.getService("activity"));
USB
android.os.IUsb usbService
= android.os.IUsb.Stub.asInterface(sm.getService("USB"));
Alarm
android.app.IAlarmManager alarmService
= android.app.IAlarmManager.Stub.asInterface(sm.getService("alarm"));
Content
android.content.IContentService contentService
= android.content.IContentService.Stub.asInterface(sm.getService("content"));
Location
android.location.ILocationManager locationService
= android.location.ILocationManager.Stub.asInterface(sm.getService("location"));
Notification
android.app.INotificationManager notificationService
= android.app.INotificationManager.Stub.asInterface(sm.getService("notification"));
Bluetooth
org.bluez.IBluetoothService bluetoothService
= org.bluez.IBluetoothService.Stub.asInterface(sm.getService("org.bluez.bluetooth_service"));
Phone
android.telephony.IPhone phoneService
= android.telephony.IPhone.Stub.asInterface(sm.getService("phone"));
StatusBar
android.server.status.IStatusBar statusbarService
= android.server.status.IStatusBar.Stub.asInterface(sm.getService("statusbar"));
Vibrator
android.os.IVibratorService vibratorService
= android.os.IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));
Volume
android.view.IRingerVolume volumeService출처:
= android.view.RingerVolumeNative.asInterface(sm.getService("volume"));
http://davanum.wordpress.com/2007/12/14/android-accessing-the-system-services/
관련글:
http://codemuri.tistory.com/entry/번역-안드로이드에서-숨겨진-시스템-서비스에-접근하기
apk 및 .jar 파일을 재수정하여 패키징하는 방법
물론 이 의도하지 않은 코드가 실행되기까지는 권한등과 같은 안드로이드의 여러가지 보안 기법이 적용되어 보호될 수도 있지만 루팅된 폰 (특히, super user 권한이 있는)은 특히 위험하게 되는 것입니다.
하지만 이 기법은 안드로이드 테스팅 쪽에서는 훌륭하게 사용될 수 있습니다. 기술이란 어떻게 쓰이느냐에 따라 동전의 양면과 같습니다.
참고 사이트는 아래와 같습니다.
동영상 링크
실행중인 Task 리스트 얻기
아래 코드 참고
ActivityManager activityManager = (ActivityManager) mContext.getSystemService( mContext.ACTIVITY_SERVICE); List<RunningTaskInfo> info; info = activityManager.getRunningTasks(7); for (Iterator iterator = info.iterator(); iterator.hasNext();) { RunningTaskInfo runningTaskInfo = (RunningTaskInfo) iterator.next(); // Do something ... }
위에서 getRunningTasks 이 파라미터는 maxNum 인데, 이 값을 1을 주면 화면 top 에 있는 태스크를 알 수 있습니다. 이 태스크라 함은 패키지명과 동일합니다. 실행 가능한 패키지 명 가져오기는 아래 링크를 참고하면 됩니다.
http://codemuri.tistory.com/entry/%EC%8B%A4%ED%96%89%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EB%AA%A9%EB%A1%9D-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0
[펌] 하나의 프로세스에서 여러 애플리케이션 실행하기
글쓴이: 회색(http://graynote.tistory.com)
안드로이드는 백그라운드와 포어그라운드에서 여러 애플리케이션(Application)이 상호 연동해서 동작할 수 있게 구성되어있습니다. 문제는 어플리케이션 프로세스(Process)가 너무 자주 그리고 많이 생성되는 것은 메모리와 CPU측면에서 좋지 않습니다. 상호 연동되는 어플리케이션을 여러개 만들어서 동작시키는 것이 필요한 경우에 하나의 프로세스에서 동작하도록 지정할 수 있습니다. 이것게 처리하는 것은 매우 바람직합니다.
1. AndroidManifest.xml에 android:sharedUserId를 지정합니다. 안드로이드는 어플리케이션 마다 리눅스 User ID를 할당하는데 sharedUserId는 서로 다른 어플리케이션에서 같은 User ID를 공유할 수 있도록 합니다. 같은 User ID를 공유하면 서로 파일등의 데이터를 공유할 수 있고 프로세스도 공유할 수 있게 됩니다. 어플리케이션은 같은 Certificate로 서명되어야만 User ID를 공유할 수 있습니다.
1.
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
2.
package
=
"com.androidpub.sample"
3.
android:sharedUserId
=
"androidpub.user"
4.
android:versionCode
=
"1"
5.
android:versionName
=
"1.0"
>
2. 각 애플리케이션의 Application 태그에 android:process를 같은 값으로 지정합니다.
1.
<
application
android:icon
=
"@drawable/icon"
android:label
=
"@string/app_name"
2.
android:process
=
"androidpub.process.share"
>
유의해야할 점은 Application Process를 공유함으로써 Application Context도 공유된다는 점입니다.
그리고 어플리케이션 업데이트시에 User ID가 바뀌는 경우 기존 데이터가 리셋되는것 같습니다. 이미 퍼블리쉬된 어플의 경우 치명적일수도 있으니 주의하셔야 합니다.
레퍼런스 : http://developer.android.com/guide/topics/manifest/manifest-intro.html
[펌] 안드로이드 소스 빌드시 일부만 빌드하기 - mmm 명령
글쓴이: 회색(http://graynote.tistory.com)
소스가 있는 위치에서 하기 명령 실행
$ . build/envsetup.sh
(위 명령이 안되면: $ source ./build/envsetup.sh)
이후,
$ mmm packages/apps/Contacts
와 같이 Contacts 부분만 다시 빌드됩니다. Android.mk 가 존재하는 Path만 적용할 수 있습니다.
$ make snod
를 실행하면 위에서 빌드한 Contacts 를 적용한 system.img 를 다시 빠르게 생성합니다.
그리고 한글등이 들어갈 때 utf8 인코딩을 쓰게되는 데 안드로이드 플랫폼 소스 빌드시에 ajvac 가 ascii 인코딩으로 설정되어 있습니다.
build/core/definitions.mk 에서 -encoding ascii 를 -encoding utf8 로 바꿔주면 됩니다. utf8 소스도 사용할 수 있습니다.
그리고 mmm 과 별도로
$make sdk
를 통해 SDK 를 만들 수 있습니다...
Android 프레임워크에서 사용하는 uid 의 종류
public PackageManagerService(Context context, boolean factoryTest) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); if (mSdkVersion <= 0) { Slog.w(TAG, "**** ro.build.version.sdk not set!"); } mContext = context; mFactoryTest = factoryTest; mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type")); mMetrics = new DisplayMetrics(); mSettings = new Settings(); mSettings.addSharedUserLP("android.uid.system", Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM); mSettings.addSharedUserLP("android.uid.phone", MULTIPLE_APPLICATION_UIDS ? RADIO_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); mSettings.addSharedUserLP("android.uid.log", MULTIPLE_APPLICATION_UIDS ? LOG_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); mSettings.addSharedUserLP("android.uid.nfc", MULTIPLE_APPLICATION_UIDS ? NFC_UID : FIRST_APPLICATION_UID, ApplicationInfo.FLAG_SYSTEM); // 중략 ...
"android.uid.system"
"android.uid.phone"
"android.uid.log"
"android.uid.nfc"
등이 있네요. 위의 uid 와 같은 키로 signing 을 하게 되면 동일한 권한을 가지게 됩니다.
ADB 디버깅 로그
헌데 막상 디버깅을 해보니 문제점이 있었습니다. 정작 알고자 하는 기능은 fork 되는 자식 프로세스에서 하게 되어 있는데 윈도우즈에서는 gdb 로 fork 된 프로세스를 디버깅할 수 없었습니다.
linux 에서는 몇가지 옵션을 설정하면 되는 것 같았는데, 윈도우즈에서는 (제가 몰라서인지...) 가능하지 않더군요.
그동안의 삽질을 뒤로하고 다른 일을 하다가...
다시 adb 의 동작 원리를 분석해야할 때가 왔습니다. 다음 3가지 사항을 고려해야 하는데...
1. 진입점에 키 입력을 받을 때까지 기다리도록 하여 fork시 정지시켜 놓고 attach 를 하느냐...
2. adb start-server 를 입력하면 fork 를 하는가? -> 하지 않는다면 그걸로 ㅇㅋ
3. 디버깅을 하기 위해 linux 에서 빌드하느냐... 시간이...ㄷㄷ
이 중에 어떻게 되려나요~
결국 윈도우즈에서 디버깅하는 방법은 성공하지 못했습니다. 그것보다 더 쉬운 방법을 찾았습니다. 제가 알고자 했던 내용은 adb 데몬과 adb host 간의 통신 프로토콜 이었습니다. 이는 사실 adb 를 tcp 를 이용하여 연결한 후 Wireshark 와 같은 도구로 모니터링을 해보면 간단한 문제였습니다.
캡처된 패킷과 adb 소스, ddmlib 소스등을 뒤적거려 보니 궁금했던 점이 모두 해결되더군요. 혹시 저와 같이 adbd 와 adb host 간의 프로토콜을 파악하시려는 분은 패킷 분석을 이용하시면 보다 쉽게 이해하실 수 있으실 겁니다.
성능 벤치마킹 App
How to discover memory usage of my application in Android
stdout 와 stderr 출력 보기
디폴트로, 안드로이드 시스템은 stdout (System.out) 와 stderr(System.err) 의 출력을 /dev/null 로 전송한다. Dalvi VM 을 실행하는 프로세스 내에서는, 시스템의 출력을 로그 파일에 전송하도록 할 수 있다. 이 경우, 시스템은 해당 메시지를 I(영문) 우선순위의 stdout 과 stderr 태그를 가진 로그를 전송한다. (아래 그림에서 System.out 이라고 찍힌 부분) 이런식으로 출력을 재지정하기 위해서는, 실행중인 에뮬레이터 또는 장치를 멈추고, setprop 명령을 이용하여 출력 재지정을 활성화 해야 한다. $ adb shell stop $ adb shell setprop log.redirect-stdio true $ adb shell start 시스템은 에뮬레이터 또는 장치가 종료될 때까지 이 설정을 유지한다. 에뮬레이터 또는 장치에 디폴트로 설정하기 위해서는, /data/local.prop 에 이 값을 추가할 수 있다. |
Wireless Adb Debugging (TCP 를 이용한 adb 디버깅) - Rooting Only
$ adb devices
$ adb tcpip 5555
$ adb connect 192.168.0.4:5555
$ su # setprop service.adb.tcp.port 5555 # stop adbd # start adbd
Process p; try { // Preform su to get root privledges p = Runtime.getRuntime().exec("su"); // Attempt to write a file to a root-only DataOutputStream os = new DataOutputStream(p.getOutputStream()); os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n"); // Close the terminal os.writeBytes("exit\n"); os.flush(); try { p.waitFor(); if (p.exitValue() != 255) { // TODO Code to run on success toastMessage("root"); } else { // TODO Code to run on unsuccessful toastMessage("not root"); } } catch (InterruptedException e) { // TODO Code to run in interrupted exception toastMessage("not root"); } } catch (IOException e) { // TODO Code to run in input/output exception toastMessage("not root"); }
$ adb shell getprop
$ adb shell setprop service.adb.tcp.port -1
$ adb shell setprop persist.adb.tcp.port 5555
안드로이드 CPU Usage & Memory Usage 가져오기
$ adb shell top -n 1
$ adb shell top --help
Runtime runtime = Runtime.getRuntime(); Process process; String res = "-0-"; try { String cmd = "top -n 1"; process = runtime.exec(cmd); InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line ; while ((line = br.readLine()) != null) { String segs[] = line.trim().split("[ ]+"); if (segs[0].equalsIgnoreCase([Your Process ID])) { res = segs[1]; break; } } } catch (Exception e) { e.fillInStackTrace(); Log.e("Process Manager", "Unable to execute top command"); }
$ adb shell dumpsys meminfo $ adb shell dumpsys meminfo [processname]
Droid Explorer
Security Permissions in Android
As we all know whenever we use a particular feature or API we need to request the permission in AndroidManifest.xml file with uses-permission element. If we don’t specify any permissions, then the application will not have any permission and application can do anything that does not require a permission.This link explains the permissions in android in more detail and this link lists the permissions in Android.
Permissions are granted to the application by package installer while installing. But not all the permissions will be granted to the system. There are some system permission which will not be granted to the user applications, but only to the system applications. Following are some of the permissions that may NOT be granted to the user application.
android.permission.ACCESS_CHECKIN_PROPERTIES android.permission.ACCESS_SURFACE_FLINGER android.permission.ACCOUNT_MANAGER android.permission.BIND_APPWIDGET android.permission.BIND_DEVICE_ADMIN android.permission.BIND_INPUT_METHOD android.permission.BIND_WALLPAPER android.permission.BRICK android.permission.BROADCAST_PACKAGE_REMOVED android.permission.BROADCAST_SMS android.permission.BROADCAST_WAP_PUSH android.permission.CALL_PRIVILEGED android.permission.CHANGE_COMPONENT_ENABLED_STATE android.permission.CLEAR_APP_USER_DATA android.permission.CONTROL_LOCATION_UPDATES android.permission.DELETE_CACHE_FILES android.permission.DELETE_PACKAGES android.permission.DEVICE_POWER android.permission.DIAGNOSTIC android.permission.FACTORY_TEST android.permission.FORCE_BACK android.permission.GLOBAL_SEARCH android.permission.HARDWARE_TEST android.permission.INJECT_EVENTS android.permission.INSTALL_LOCATION_PROVIDER android.permission.INSTALL_PACKAGES android.permission.INTERNAL_SYSTEM_WINDOW android.permission.MANAGE_APP_TOKENS android.permission.MASTER_CLEAR android.permission.READ_FRAME_BUFFER android.permission.READ_INPUT_STATE android.permission.REBOOT android.permission.SET_ACTIVITY_WATCHER android.permission.SET_ORIENTATION android.permission.SET_PREFERRED_APPLICATIONS android.permission.SET_TIME android.permission.STATUS_BAR android.permission.UPDATE_DEVICE_STATS android.permission.WRITE_GSERVICES android.permission.WRITE_SECURE_SETTINGS
To get these permissions, the application must be signed with the key which used to sign the platform. This may be different for manufacturers. So it practically not possible to get these permissions granted to a user application.
Note: While playing with PowerManager.reboot
I was so stupid I thought my application will be granted the permission android.permission.REBOOT
, but it was not granted. Then I created an application requesting all the permissions and above list of permissions are not granted. Hope this will help you when you request a permission next time.
Source: http://www.krvarma.com/posts/android/security-permissions-in-android/
Gingerbread NDK Awesomeness
In fact, with these new tools, applications targeted at Gingerbread or later can be implemented entirely in C++; you can now build an entire Android application without writing a single line of Java. |
사실, 이 새로운 도구를 통해 진저브레드 혹은 그 이후 버전을 지원하는 어플리케이션을 순수하게 C++로만 구현할 수 있게 되었습니다. 한 줄의 Java 코드 없이 전체 안드로이드 어플리케이션을 만들 수 있게 된 것입니다. |
실행가능한 애플리케이션 목록 가져오기
public class Grid1 extends Activity { GridView mGrid; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); loadApps(); // do this in onresume? setContentView(R.layout.grid_1); mGrid = (GridView) findViewById(R.id.myGrid); mGrid.setAdapter(new AppsAdapter()); } private List<resolveinfo> mApps; private void loadApps() { Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); mApps = getPackageManager().queryIntentActivities(mainIntent, 0); } public class AppsAdapter extends BaseAdapter { public AppsAdapter() { } public View getView(int position, View convertView, ViewGroup parent) { ImageView i; if (convertView == null) { i = new ImageView(Grid1.this); i.setScaleType(ImageView.ScaleType.FIT_CENTER); i.setLayoutParams(new GridView.LayoutParams(50, 50)); } else { i = (ImageView) convertView; } ResolveInfo info = mApps.get(position); i.setImageDrawable(info.activityInfo.loadIcon(getPackageManager())); return i; } public final int getCount() { return mApps.size(); } public final Object getItem(int position) { return mApps.get(position); } public final long getItemId(int position) { return position; } } }
[펌] 소스 #3 - Dialog 없이 wheel 만 있는 ProgressBar 만들고 WebView 위에서 사용하기
Local Service and Remote Service ( AIDL Service )
package com.sskk.sample.localservicetest.service; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import com.sskk.sample.localservicetest.MainActivity; import com.sskk.sample.localservicetest.R; public class BackgroundService extends Service { private NotificationManager notificationMgr; @Override public void onCreate() { super.onCreate(); notificationMgr =(NotificationManager)getSystemService( NOTIFICATION_SERVICE); displayNotificationMessage("starting Background Service"); Thread thr = new Thread(null, new ServiceWorker(), "BackgroundService"); thr.start(); } class ServiceWorker implements Runnable { public void run() { // do background processing here... // stop the service when done... // BackgroundService.this.stopSelf(); } } @Override public void onDestroy() { displayNotificationMessage("stopping Background Service"); super.onDestroy(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public IBinder onBind(Intent intent) { return null; } private void displayNotificationMessage(String message) { Notification notification = new Notification(R.drawable.note, message,System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0); notification.setLatestEventInfo(this, "Background Service",message, contentIntent); notificationMgr.notify(R.id.app_notification_id, notification); } }
package com.sskk.sample.service; interface IStockQuoteService { double getQuote(String ticker); }
package com.sskk.sample.service; import com.sskk.sample.service.IStockQuoteService; import com.sskk.sample.service.IStockQuoteService.Stub; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; public class StockQuoteService extends Service { private static final String TAG = "StockQuoteService"; public class StockQuoteServiceImple extends IStockQuoteService.Stub { @Override public double getQuote(String ticker) throws RemoteException { Log.v(TAG, "종목 " + ticker + "에 대해 getQuote() 호출됨"); return 20.0; } } @Override public IBinder onBind(Intent p_intent) { Log.v(TAG, "onBind 호출됨"); return new StockQuoteServiceImple(); } @Override public void onCreate() { super.onCreate(); Log.v(TAG, "onCreate 호출됨"); } @Override public void onDestroy() { super.onDestroy(); Log.v(TAG, "onDestroy 호출됨"); } @Override public void onStart(Intent p_intent, int p_startId) { super.onStart(p_intent, p_startId); Log.v(TAG, "onStart 호출됨"); } }
package com.sskk.sample.service; parcelable Person;
package com.sskk.sample.service; import android.os.Parcel; import android.os.Parcelable; public class Person implements Parcelable { private int mAge; private String mName; public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() { @Override public Person createFromParcel(Parcel in) { return new Person(in); } @Override public Person[] newArray(int size) { return new Person[size]; } }; public Person() { } private Person(Parcel in) { readFromParcel(in); } public void readFromParcel(Parcel in) { mAge = in.readInt(); mName = in.readString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mAge); out.writeString(mName); } public int getAge() { return mAge; } public void setAge(int age) { mAge = age; } public String getName() { return mName; } public void setName(String name) { mName = name; } }
package com.sskk.sample.service; import com.sskk.sample.service.Person; interface IStockQuoteService2 { String getQuote(in String ticker, in Person requester); }
package com.sskk.sample.service; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import com.sskk.sample.aidltest.NotiActivity; import com.sskk.sample.aidltest.R; public class StockQuoteService2 extends Service { private NotificationManager mNotificationManager; public class StockQuoteServiceImple2 extends IStockQuoteService2.Stub { @Override public String getQuote(String ticker, Person requester) throws RemoteException { // TODO Auto-generated method stub return "안녕하세요, " + requester.getName() + "!" + ticker + "의 주가는 20.0 입니다."; } } @Override public void onCreate() { super.onCreate(); mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); displayNotificationMessage("onCreate 가 호출됨"); } @Override public void onDestroy() { displayNotificationMessage("onDestroy 가 호출됨"); super.onDestroy(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public IBinder onBind(Intent intent) { displayNotificationMessage("onBind 가 호출됨"); return new StockQuoteServiceImple2(); } private void displayNotificationMessage(String message) { Notification notification = new Notification(R.drawable.note, message, System.currentTimeMillis()); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, NotiActivity.class), 0); notification.setLatestEventInfo(this, "StockQuoteService2", message, contentIntent); mNotificationManager.notify(R.id.app_notification_id, notification); } }
HttpClient 및 URL 테스트
HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI("http://www.645lotto.net/Confirm/number.asp?sltSeq=" + game)); HttpResponse response = client.execute(request); BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
URL url = new URL("http://www.645lotto.net/Confirm/number.asp?sltSeq=" + game); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
package com.sskk.example.HttpClientTest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.util.ArrayList; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.app.Activity; import android.os.Bundle; public class HttpClientTest extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayListnumbers = GetLottoNumber1(1); for(Integer number : numbers) { System.out.print(number + " "); } System.out.println(); numbers = GetLottoNumber2(2); for(Integer number : numbers) { System.out.print(number + " "); } System.out.println(); } public static ArrayList GetLottoNumber1(final int game) { ArrayList numberList = new ArrayList (); try { HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI("http://www.645lotto.net/Confirm/number.asp?sltSeq=" + game)); HttpResponse response = client.execute(request); BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); String tempStr; StringBuilder htmlSource = new StringBuilder(); while((tempStr = in.readLine()) != null) { htmlSource.append(tempStr); } in.close(); int first = htmlSource.indexOf("class=\"sboll2"); if(first == -1) return null; int last = htmlSource.indexOf("/div>", first); if(last == -1) return null; String numberHtml = htmlSource.substring(first, last); final String search = "../images/Comm/s"; final int length = search.length(); int firstIndex = 0; while(true) { int found = numberHtml.indexOf(search, firstIndex); if(found == -1) break; int dotFound = numberHtml.indexOf(".", found + length); if(dotFound == -1) break; String numberStr = numberHtml.substring(found + length, dotFound); try { Integer number = Integer.parseInt(numberStr); numberList.add(number); // System.out.println(number); } catch(Exception e) { } firstIndex = found + length; } } catch(Exception e) { e.printStackTrace(); } if(numberList.size() != 7) { return null; } return numberList; } public static ArrayList GetLottoNumber2(final int game) { ArrayList numberList = new ArrayList (); try { URL url = new URL("http://www.645lotto.net/Confirm/number.asp?sltSeq=" + game); BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); String tempStr; StringBuilder htmlSource = new StringBuilder(); while((tempStr = in.readLine()) != null) { htmlSource.append(tempStr); } in.close(); int first = htmlSource.indexOf("class=\"sboll2"); if(first == -1) return null; int last = htmlSource.indexOf("/div>", first); if(last == -1) return null; String numberHtml = htmlSource.substring(first, last); final String search = "../images/Comm/s"; final int length = search.length(); int firstIndex = 0; while(true) { int found = numberHtml.indexOf(search, firstIndex); if(found == -1) break; int dotFound = numberHtml.indexOf(".", found + length); if(dotFound == -1) break; String numberStr = numberHtml.substring(found + length, dotFound); try { Integer number = Integer.parseInt(numberStr); numberList.add(number); // System.out.println(number); } catch(Exception e) { } firstIndex = found + length; } }catch(MalformedURLException e) { } catch(IOException e) { e.printStackTrace(); } if(numberList.size() != 7) { return null; } return numberList; } }
ContentProvider Example
package com.sskk.example.bookprovidertest.provider; import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; import com.sskk.example.bookprovidertest.provider.BookProviderMetaData.BookTableMetaData; public class BookProvider extends ContentProvider { private final static String TAG="tag"; //Create a Projection Map for Columns //Projection maps are similar to "as" construct in an sql //statement whereby you can rename the //columns. private static HashMapsBooksProjectionMap; static { sBooksProjectionMap = new HashMap (); sBooksProjectionMap.put(BookTableMetaData._ID, BookTableMetaData._ID); //name, isbn, author sBooksProjectionMap.put(BookTableMetaData.BOOK_NAME , BookTableMetaData.BOOK_NAME); sBooksProjectionMap.put(BookTableMetaData.BOOK_ISBN , BookTableMetaData.BOOK_ISBN); sBooksProjectionMap.put(BookTableMetaData.BOOK_AUTHOR , BookTableMetaData.BOOK_AUTHOR); //created date, modified date sBooksProjectionMap.put(BookTableMetaData.CREATED_DATE , BookTableMetaData.CREATED_DATE); sBooksProjectionMap.put(BookTableMetaData.MODIFIED_DATE , BookTableMetaData.MODIFIED_DATE); } //Provide a mechanism to identify all the incoming uri patterns. private static final UriMatcher sUriMatcher; private static final int INCOMING_BOOK_COLLECTION_URI_INDICATOR = 1; private static final int INCOMING_SINGLE_BOOK_URI_INDICATOR = 2; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(BookProviderMetaData.AUTHORITY , "books" , INCOMING_BOOK_COLLECTION_URI_INDICATOR); sUriMatcher.addURI(BookProviderMetaData.AUTHORITY , "books/#", INCOMING_SINGLE_BOOK_URI_INDICATOR); } // Deal with OnCreate call back private DatabaseHelper mOpenHelper; @Override public boolean onCreate() { mOpenHelper = new DatabaseHelper(getContext()); return true; } private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context) { super(context, BookProviderMetaData.DATABASE_NAME, null , BookProviderMetaData.DATABASE_VERSION); } //Create the database @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + BookTableMetaData.TABLE_NAME + " (" + BookProviderMetaData.BookTableMetaData._ID + " INTEGER PRIMARY KEY," + BookTableMetaData.BOOK_NAME + " TEXT," + BookTableMetaData.BOOK_ISBN + " TEXT," + BookTableMetaData.BOOK_AUTHOR + " TEXT," + BookTableMetaData.CREATED_DATE + " INTEGER," + BookTableMetaData.MODIFIED_DATE + " INTEGER" + ");"); } //Deal with version changes @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data"); db.execSQL("DROP TABLE IF EXISTS " + BookTableMetaData.TABLE_NAME); onCreate(db); } } @Override public String getType(Uri uri) { switch (sUriMatcher.match(uri)) { case INCOMING_BOOK_COLLECTION_URI_INDICATOR: return BookTableMetaData.CONTENT_TYPE; case INCOMING_SINGLE_BOOK_URI_INDICATOR: return BookTableMetaData.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("Unknown URI " + uri); } } @Override public Cursor query(Uri uri, String[] projection, String selection , String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); switch (sUriMatcher.match(uri)) { case INCOMING_BOOK_COLLECTION_URI_INDICATOR: qb.setTables(BookTableMetaData.TABLE_NAME); qb.setProjectionMap(sBooksProjectionMap); break; case INCOMING_SINGLE_BOOK_URI_INDICATOR: qb.setTables(BookTableMetaData.TABLE_NAME); qb.setProjectionMap(sBooksProjectionMap); qb.appendWhere(BookTableMetaData._ID + "=" + uri.getPathSegments().get(1)); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } // If no sort order is specified use the default String orderBy; if (TextUtils.isEmpty(sortOrder)) { orderBy = BookTableMetaData.DEFAULT_SORT_ORDER; } else { orderBy = sortOrder; } // Get the database and run the query SQLiteDatabase db = mOpenHelper.getReadableDatabase(); Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy); int i = c.getCount(); // Tell the cursor what uri to watch, // so it knows when its source data changes c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public Uri insert(Uri uri, ContentValues values) { // Validate the requested uri if (sUriMatcher.match(uri) != INCOMING_BOOK_COLLECTION_URI_INDICATOR) { throw new IllegalArgumentException("Unknown URI " + uri); } Long now = Long.valueOf(System.currentTimeMillis()); //validate input fields // Make sure that the fields are all set if (values.containsKey(BookTableMetaData.CREATED_DATE) == false) { values.put(BookTableMetaData.CREATED_DATE, now); } if (values.containsKey(BookTableMetaData.MODIFIED_DATE) == false) { values.put(BookTableMetaData.MODIFIED_DATE, now); } if (values.containsKey(BookTableMetaData.BOOK_NAME) == false) { throw new SQLException( "Failed to insert row because Book Name is needed " + uri); } if (values.containsKey(BookTableMetaData.BOOK_ISBN) == false) { values.put(BookTableMetaData.BOOK_ISBN, "Unknown ISBN"); } if (values.containsKey(BookTableMetaData.BOOK_AUTHOR) == false) { values.put(BookTableMetaData.BOOK_ISBN, "Unknown Author"); } SQLiteDatabase db = mOpenHelper.getWritableDatabase(); long rowId = db.insert(BookTableMetaData.TABLE_NAME , BookTableMetaData.BOOK_NAME, values); if (rowId > 0) { Uri insertedBookUri = ContentUris.withAppendedId( BookTableMetaData.CONTENT_URI, rowId); getContext().getContentResolver().notifyChange(insertedBookUri, null); return insertedBookUri; } throw new SQLException("Failed to insert row into " + uri); } @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count; switch (sUriMatcher.match(uri)) { case INCOMING_BOOK_COLLECTION_URI_INDICATOR: count = db.update(BookTableMetaData.TABLE_NAME, values, where, whereArgs); break; case INCOMING_SINGLE_BOOK_URI_INDICATOR: String rowId = uri.getPathSegments().get(1); count = db.update(BookTableMetaData.TABLE_NAME , values , BookTableMetaData._ID + "=" + rowId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : "") , whereArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int delete(Uri uri, String where, String[] whereArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count; switch (sUriMatcher.match(uri)) { case INCOMING_BOOK_COLLECTION_URI_INDICATOR: count = db.delete(BookTableMetaData.TABLE_NAME, where, whereArgs); break; case INCOMING_SINGLE_BOOK_URI_INDICATOR: String rowId = uri.getPathSegments().get(1); count = db.delete(BookTableMetaData.TABLE_NAME , BookTableMetaData._ID + "=" + rowId + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : "") , whereArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } }
package com.sskk.example.bookprovidertest.provider; import android.net.Uri; import android.provider.BaseColumns; public class BookProviderMetaData { public static final String AUTHORITY = "com.sskk.example.bookprovidertest.provider.BookProvider"; public static final String DATABASE_NAME = "book.db"; public static final int DATABASE_VERSION = 1; public static final String BOOKS_TABLE_NAME = "books"; private BookProviderMetaData() {} //inner class describing BookTable public static final class BookTableMetaData implements BaseColumns { private BookTableMetaData() {} public static final String TABLE_NAME = "books"; //uri and MIME type definitions public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/books"); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.androidbook.book"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.androidbook.book"; public static final String DEFAULT_SORT_ORDER = "modified DESC"; //Additional Columns start here. //string type public static final String BOOK_NAME = "name"; //string type public static final String BOOK_ISBN = "isbn"; //string type public static final String BOOK_AUTHOR = "author"; //Integer from System.currentTimeMillis() public static final String CREATED_DATE = "created"; //Integer from System.currentTimeMillis() public static final String MODIFIED_DATE = "modified"; } }
package com.sskk.example.bookprovidertest; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import com.sskk.example.bookprovidertest.provider.BookProviderMetaData; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); deleteTest(); insertTest(); readTest(); } private void readTest() { ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(BookProviderMetaData.BookTableMetaData.CONTENT_URI, null, null, null, null); // 행 갯수 출력 Log.d(TAG, "Cursor Count: " + cursor.getCount()); // 커서 내용 읽기 if(cursor.moveToFirst() == true) { do { int nameColumn = cursor.getColumnIndex(BookProviderMetaData.BookTableMetaData.BOOK_NAME); int authorColumn = cursor.getColumnIndex(BookProviderMetaData.BookTableMetaData.BOOK_AUTHOR); int isbnColumn = cursor.getColumnIndex(BookProviderMetaData.BookTableMetaData.BOOK_ISBN); String name = cursor.getString(nameColumn); String author = cursor.getString(authorColumn); String isbn = cursor.getString(isbnColumn); Log.d(TAG, name + " " + author + " " + isbn); } while(cursor.moveToNext()); } } private void deleteTest() { ContentResolver contentResolver = getContentResolver(); contentResolver.delete(BookProviderMetaData.BookTableMetaData.CONTENT_URI, null, null); Cursor cursor = contentResolver.query(BookProviderMetaData.BookTableMetaData.CONTENT_URI, null, null, null, null); // 행 갯수 출력 Log.d(TAG, "Cusor Count: " + cursor.getCount()); } private void insertTest() { ContentResolver contentResolver = getContentResolver(); Cursor cursor = contentResolver.query(BookProviderMetaData.BookTableMetaData.CONTENT_URI, null, null, null, null); if(cursor.getCount() != 0) return; // 행 추가 ContentValues values = new ContentValues(); values.put(BookProviderMetaData.BookTableMetaData.BOOK_NAME, "Sonagi"); values.put(BookProviderMetaData.BookTableMetaData.BOOK_AUTHOR, "HwangSunWon"); values.put(BookProviderMetaData.BookTableMetaData.BOOK_ISBN, "isbn-0033"); Uri uri = contentResolver.insert(BookProviderMetaData.BookTableMetaData.CONTENT_URI, values); values = new ContentValues(); values.put(BookProviderMetaData.BookTableMetaData.BOOK_NAME, "HaakHaak"); values.put(BookProviderMetaData.BookTableMetaData.BOOK_AUTHOR, "LeeOiSu"); values.put(BookProviderMetaData.BookTableMetaData.BOOK_ISBN, "isbn-0034"); uri = contentResolver.insert(BookProviderMetaData.BookTableMetaData.CONTENT_URI, values); } }