devflow.kr@:~#

Google Proximity Beacons

ANDROID

https://newcircle.com/s/post/1755/2015/08/31/google-proximity-beacons---part-1

https://newcircle.com/s/post/1761/2015/09/11/google-proximity-beacons---part-2

저작자 표시 비영리 동일 조건 변경 허락
신고

Retrofit 한국어 API 문서

ANDROID

크리스마스 기념으로 Retrofit의 API 문서를 번역하였다.

번역 실력이 매우 구져서 걱정이다.


아래 링크에서 볼 수 있다.


http://devflow.github.io/retrofit-kr/

저작자 표시 비영리 동일 조건 변경 허락
신고

Picasso를 LinearLayout의 배경 설정으로 사용하기.

ANDROID

Picasso 라이브러리의 핵심기능 중 RequestCreator의 into() 함수에는 Target이라는 인터페이스를 파라미터로하는 함수가있는데, 이를 이용하면 간단하게 해결이 가능하다. Target을 implements하는 클래스로 만들어 주면 된다.


public class PicassoableLinearLayout extends LinearLayout implements Target {
    public PicassoableLinearLayout(Context context) {
        super(context);
    }

    public PicassoableLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PicassoableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @SuppressLint("NewApi")
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {

        int sdk = android.os.Build.VERSION.SDK_INT;
        if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setBackgroundDrawable(new BitmapDrawable(getResources(), bitmap));
        } else {
            setBackground(new BitmapDrawable(getResources(), bitmap));
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onBitmapFailed(Drawable drawable) {
        int sdk = android.os.Build.VERSION.SDK_INT;
        if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setBackgroundDrawable(drawable);
        } else {
            setBackground(drawable);
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onPrepareLoad(Drawable drawable) {
        int sdk = android.os.Build.VERSION.SDK_INT;
        if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            setBackgroundDrawable(drawable);
        } else {
            setBackground(drawable);
        }

    }
}



저작자 표시 비영리 동일 조건 변경 허락
신고

DrawerLayout의 드래그 가능부분(엣지) 변경하기

ANDROID
 public void setDrawerLeftEdgeSize( DrawerLayout drawerLayout, float displayWidthPercentage) {
        try {
            // find ViewDragHelper and set it accessible
            Field leftDraggerField = drawerLayout.getClass().getDeclaredField(
                    "mLeftDragger");
            leftDraggerField.setAccessible(true);
            ViewDragHelper leftDragger = (ViewDragHelper) leftDraggerField
                    .get(drawerLayout);
            // find edgesize and set is accessible
            Field edgeSizeField = leftDragger.getClass().getDeclaredField(
                    "mEdgeSize");
            edgeSizeField.setAccessible(true);
            int edgeSize = edgeSizeField.getInt(leftDragger);

            // set new edgesize
            Point displaySize = new Point();
            getActivity().getWindowManager().getDefaultDisplay()
                    .getSize(displaySize);
            edgeSizeField.setInt(leftDragger,
                    (int) (displaySize.x * displayWidthPercentage));
        } catch (NoSuchFieldException e) {
            // ignore
        } catch (IllegalArgumentException e) {
            // ignore
        } catch (IllegalAccessException e) {
            // ignore
        }
    }

단, 위 소스를 사용할시, 드래그 허용 퍼센트(화면의 X크기)가 DrawerView(드래그해서 튀어나오는 메뉴)의 Width보다 크다면, LongClick과, 드래그에 오묘한 현상이 일어나게 된다. 즉 slideoffest이 1.0f 이상이 나올 수 있다는 점이다. 이 점 생각해 적당하게 설정하기 바람

저작자 표시 비영리 동일 조건 변경 허락
신고

ViewPager의 Fragment 안에 DrawerLayout 사용시 문제.

ANDROID


ViewPager의 Fragment 페이지 안에서 DrawerLayout을 사용할시(ViewPager의 Swap기능은 OFF라고 가정.), 드래그해서 Drawer를 여는 부분에 문제가 생기게 된다.


이유는 ViewPager가 DrawerLayout의 바로 Parent가 되면 발생하는 문제이다. 


이때 DrawerLayout을 Root로 지정하지말아야한다. 간단하게 LinearLayout을 Root로 한 후, 바로 아래에 DrawerLayout이 되는 형태를 사용하여야 한다.



예) ViewPager -> Fragment -> LinearLayout -> DrawerLayout -> Content, DrawerView

저작자 표시 비영리 동일 조건 변경 허락
신고

Android 기기 식별에 대해

ANDROID

Identifying Devices

Suppose you feel that for the needs of your application, you need an actual hardware device identifier. This turns out to be a tricky problem.

In the past, when every Android device was a phone, things were simpler: TelephonyManager.getDeviceId() is required to return (depending on the network technology) the IMEI, MEID, or ESN of the phone, which is unique to that piece of hardware.

However, there are problems with this approach:

  • Non-phones: Wifi-only devices or music players that don’t have telephony hardware just don’t have this kind of unique identifier.

  • Persistence: On devices which do have this, it persists across device data wipes and factory resets. It’s not clear at all if, in this situation, your app should regard this as the same device.

  • Privilege:It requires READ_PHONE_STATE permission, which is irritating if you don’t otherwise use or need telephony.

  • Bugs: We have seen a few instances of production phones for which the implementation is buggy and returns garbage, for example zeros or asterisks.

Mac Address

It may be possible to retrieve a Mac address from a device’s WiFi or Bluetooth hardware. We do not recommend using this as a unique identifier. To start with, not all devices have WiFi. Also, if the WiFi is not turned on, the hardware may not report the Mac address.

Serial Number

Since Android 2.3 (“Gingerbread”) this is available via android.os.Build.SERIAL. Devices without telephony are required to report a unique device ID here; some phones may do so also.

ANDROID_ID

More specifically, Settings.Secure.ANDROID_ID. This is a 64-bit quantity that is generated and stored when the device first boots. It is reset when the device is wiped.

ANDROID_ID seems a good choice for a unique device identifier. There are downsides: First, it is not 100% reliable on releases of Android prior to 2.2 (“Froyo”). Also, there has been at least one widely-observed bug in a popular handset from a major manufacturer, where every instance has the same ANDROID_ID.

Conclusion

For the vast majority of applications, the requirement is to identify a particular installation, not a physical device. Fortunately, doing so is straightforward.

There are many good reasons for avoiding the attempt to identify a particular device. For those who want to try, the best approach is probably the use of ANDROID_ID on anything reasonably modern, with some fallback heuristics for legacy devices.


출저 : http://android-developers.blogspot.kr/2011/03/identifying-app-installations.html

저작자 표시 비영리 동일 조건 변경 허락
신고

Android WebView clearHistory 사용하는 법

ANDROID

WebView에서 History를 지워야할 때 가 있는데 아무곳(필자의 예로써 onBackPressed)에서는 작동을 하지 않습니다. 아니 정확히는 작동을 합니다. 하지만 반드시 WebViewClient의 onPageFinished에 넣어 줘야합니다. 아래는 해당 히스토리를 제거하는 코드입니다.


        webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                if(isClearHistory){
                    isClearHistory=false;
                    view.clearHistory();
                }
                super.onPageFinished(view, url);
            }
        });


중략


    private void LoadPage(String url){
        webView.loadUrl(url);
        isClearHistory = true;
        webView.setVisibility(View.VISIBLE);
    }


(참고로 위 코드는 LoadPage가 호출될때마다 히스토리를 클리어하는데 필자의 경우에는 특별한 경우이기 때문에 이런 방법을 사용한 것입니다. 개발자의 입장에 맞춰 수정하길 바랍니다. )

저작자 표시 비영리 동일 조건 변경 허락
신고

Android WebView 텍스트(Input) 입력시 확대/리사이징 문제

ANDROID

WebView에서 ViewPort Metatag를 가지고 있어도. Form이나 기타 TextField(input)을 입력할때 확대가 되는 버그가 발생하는데.


이때 viewport meta tag의 값을 아래와 같이 설정해 주면 TextField가 Focus되도 확대가 되지 않아 정상적으로(Y스크롤만 진행)됩니다.


width=device-width, initial-scale=1.0, user-scalable=no, height=device-height, maximum-scale=1.0, target-densityDpi=device-dpi


참고로 필자는 아래와 같은 WebView 세팅을 설정하였습니다.


        set.setJavaScriptEnabled(true);
        set.setJavaScriptCanOpenWindowsAutomatically(true);
        set.setBuiltInZoomControls(false);
        set.setSupportMultipleWindows(false);
        set.setSupportZoom(false);
        set.setBlockNetworkImage(false);
        set.setLoadsImagesAutomatically(true);
        set.setAllowContentAccess(true);
        set.setUseWideViewPort(false);
        set.setLoadWithOverviewMode(false);
        set.setDomStorageEnabled(true);
        set.setAppCacheEnabled(true);


위에서 굳이 필요한거만 꼽자면, setLoadWithOverviewMode, setUseWideViewPort,setSupportZoom,setBuiltInZoomControls 정도가 되겠습니다.


해당 이슈가 발생하는 이유는 WebView에서 TextField가 포커스를 잡히게되면 Soft Keyboard가 활성화되어 WebView가 Resize되기 때문입니다. 하나의 다른 해결방법으로 Manifest에 android:windowSoftInputMode="adjustPan"를 설정하면 되는데, 필자의 경우에는 Fixed 레이아웃안에 TextField가 포함되어있기 때문에, WebView가 리사이징되지 않으면 Soft Keyboard가 WebView를 가려 더욱 큰 문제가 발생하기 때문에 위와같은 Meta tag를 수정하는 방법을 사용하였습니다.



저작자 표시 비영리 동일 조건 변경 허락
신고

Ringdroid(링드로이드) 소스

ANDROID



우리나라에서도 많이 알려진 안드로이드 벨소리 제작 어플리케이션중에 최고인 링드로이드는 오픈소스며 현재 구글프로젝트에서 제공중입니다. 



https://code.google.com/p/ringdroid/


위링크에서 확인하실 수 있으며 소스가 깔끔하게 작성되있으며 어느정도의 제작의 코멘트가 있어 편리합니다.

, Waveform, CheapsoundFile 클래스 등, 굉장히 유용한 코드가 있습니다.


SVN으로 http://ringdroid.googlecode.com/svn/trunk/ 를 Checkout하시거나,

https://code.google.com/p/ringdroid/source/browse/ 로 통해 소스코드를 보실 수 있습니다.

저작자 표시 비영리 동일 조건 변경 허락
신고

이클립스 ADT 추가시 Unable to read repository 오류

ANDROID

Unable to read repository at https://dl-ssl.google.com/android/eclipse/content.xml.


라는 오류와함께 Eclipse에 ADT추가가 안되는 경우가 있습니다. 



카스퍼스키 사용자분들에게 발생하는 문제였습니다. IM, Spam, Web 감시를 끄시고, eclipse.exe파일 속성에서 호환성탭 -> 관리자 권한으로 이  프로그램 실행에 체크해주셔야 정상적으로 ADT를 추가할 수 있습니다.



ADT플러그인의 주소 https://dl-ssl.google.com/android/eclipse/

저작자 표시 비영리 동일 조건 변경 허락
신고

HttpClient의 Timeout을 설정해주기.

ANDROID

HttpClient mClient = new DefaultHttpClient();

mClient.getParams().setParameter("http.protocol.expect-continue", false);

mClient.getParams().setParameter("http.connection.timeout", 2000);

mClient.getParams().setParameter("http.socket.timeout", 2000);


위와같이 설정해주시면 됩니다.

저작자 표시 비영리 동일 조건 변경 허락
신고

모든 Activity, Widget을 ICS HOLO LIGHT 로..

ANDROID

좋은 라이브러리가 있어서 포스팅해봅니다.


보통, Activity들은 OS 버전에 맞는(Gingerbread, ICS, ... )의 THEME를 따라가는데요. 아무래도 이쁜 테마는 ICS Holo Light 이잖아요, 그걸 버전과는 상관없게 사용하는 라이브러리를 찾게 되었습니다.




Screenshot 3Screenshot 4Screenshot 5




HoloEverywhere v1.4

What is it?

Bringing Holo Theme from Android 4.1 to 2.1 and above.

How to use?

  • You should clone git repo, init and update submodules:
git clone git://github.com/ChristopheVersieux/HoloEverywhere.git HoloEverywhere
cd HoloEverywhere
git submodule --init --recursive update

You also may use git GUI programs

  • Import HoloEverywhere from library folder and ActionBarSherlock from contrib/ActionBarSherlock/library folder into Eclipse

  • Add HoloEverywhere project as library into your project (Properties/Android/Library/Add)

  • Extend the Activities from org.holoeverywhere.app.***Activity

Example:

import org.holoeverywhere.app.ListActivity;

public class MainActivity extends ListActivity { ...

Also you should cast view to with the same name from package org.holoeverywhere.widget, if possible. This, for example, ProgressBar and Spinner:

import org.holoeverywhere.widget.ProgressBar;

ProgressBar bar = (ProgressBar) findViewById(R.id.progress_bar);



링크 : https://github.com/ChristopheVersieux/HoloEverywhere

저작자 표시 비영리 동일 조건 변경 허락
신고

Create a Custom-Styled UI Slider (SeekBar) in Android

ANDROID

좋은글이 있어서 첨부합니다.


선출처 : http://www.mokasocial.com/2011/02/create-a-custom-styled-ui-slider-seekbar-in-android/


MokaSocial-Blog-Headers-Slider


An Android slider (or a SeekBar as it’s called in the Android world) is a pretty slick UI tool which we recently used in our Call Your Folks! app as a means of choosing a reminder frequency between one day and three months.

I’ll walk you through creating a custom-styled seekbar for your Android application using nothing but a few XML and image drawables.

In this tutorial, I assume that you know how to implement a SeekBar in your app; if you don’t, check out the Android API demos, specifically SeekBar1.java and seekbar_1.xml.

Step 1: Create Your Image Drawables (9-Patch)

Before creating any XML drawables, make sure you create the image drawables (including one 9-patch drawable) needed for the seekbar background, handle, and progress sections. The 9-patch drawables will be put to use by the XML drawables in the steps below.

Create the following drawables and place them in your /res/drawable/ folder:

Step 2: SeekBar Progress Drawable

Now create an XML drawable for the Android seekbar progress (the blue-striped section in the example), call it seekbar_progress_bg.xml, and place it in your /res/drawable/folder:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <clip>
            <shape>
                <gradient
                    android:startColor="#FF5e8ea3"
                    android:centerColor="#FF32a0d2"
                    android:centerY="0.1"
                    android:endColor="#FF13729e"
                    android:angle="270"
                />
            </shape>
        </clip>
    </item>
    <item>
        <clip>
        <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
            android:src="@drawable/stripe_bg"
            android:tileMode="repeat"
            android:antialias="true"
            android:dither="false"
            android:filter="false"
            android:gravity="left"
        />
        </clip>
    </item>
</layer-list>

The above XML first draws a semi-transparent, blue gradient, then layers the semi-transparent stripe image on top of the gradient. The highlighted line of code (line 20) refers to the stripe (semi-transparent) image inside your drawable folder, created in Step 1.

For more information on creating custom shapes via XML, check out the Android drawable resources docs, specifically the bitmap and shape sections.

Step 3: SeekBar Background Drawable

Next create the main seekbar progress drawable; it’ll assign a drawable to the seekbarprogress and secondaryProgress actions inside your seekbar. Name your drawable something like seekbar_progress.xml, place it inside your /res/drawable/ folder:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <nine-patch
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:src="@drawable/seekbar_background"
            android:dither="true"
         />
    </item>
    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <gradient
                    android:startColor="#80028ac8"
                    android:centerColor="#80127fb1"
                    android:centerY="0.75"
                    android:endColor="#a004638f"
                    android:angle="270"
                />
            </shape>
        </clip>
    </item>
    <item
        android:id="@android:id/progress"
        android:drawable="@drawable/seekbar_progress_bg"
    />
</layer-list>

The first bit of highlighted code above (line 8) is referring to the seekbar background image (9-patch drawable) created in Step 1 and (line 29) is referring to the drawable you created above in Step 2.

Step 4: Bringing it all together…

At this point, all you need to do is call your seekbar_progress drawable when declaring your seekbar:

01
02
03
04
05
06
07
08
09
10
<SeekBar
        android:id="@+id/frequency_slider"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:max="20"
        android:progress="0"
        android:secondaryProgress="0"
        android:progressDrawable="@drawable/seekbar_progress"
        android:thumb="@drawable/seek_thumb"
/>

The two lines of highlighted code are setting the progress and thumb drawables for the SeekBar item. The @drawable/seekbar_progress refers to the XML drawable created in the previous step.

See it in action!

For a “live demo” of the seekbar bar being used, download our Call Your Folks! app.

For more information on the Android SeekBar, check out the Android docs.

저작자 표시 비영리 동일 조건 변경 허락
신고

마켓등록시 예기치 않은 오류가 발생했습니다. 나중에 다시 시도해 주세요

ANDROID



마켓에 apk를 등록할때 예기치 않은 오류가 발생했습니다. 나중에 다시 시도해 주세요 마와 같은 오류가 밣생할 때가 있다, 보통 컴퓨터를 리붓을 하거나 apk를 재 Export 하다보면 되긴하는데.. 이럴때도 안될때는 자동로그인이 되어있더라도, 로그아웃후 다시 로그인하면 정상적으로 올라간다.


단, 가끔 구글 서버가 장애가 있어서 안올라가는 이유도 있다.

저작자 표시 비영리 동일 조건 변경 허락
신고

[Android] LazyList (비동기식 이미지 다운로드 클래스)

ANDROID


LazyList

A simple library to display images in Android ListView. Images are being downloaded asynchronously in the background. Images are being cached on SD card and in memory. Can also be used for GridView and just to display images into an ImageView.

(http://github.com/thest1/LazyList/ 사이트에서 인용)


보통 Listview에서나, ImageView에서 로딩알림없이, 비동기식으로 이미지를 웹으로 불러올때 사용하는 Class입니다.


개인적으로 ImageDownloader(http://code.google.com/p/android-imagedownloader/source/browse/trunk/src/com/example/android/imagedownloader/ImageDownloader.java?r=3)도 써봤지만, LazyList만큼 만족스러운 Class 를 보지못했습니다.


무려 메모리에 캐싱가능한 MemoryCache 기능과 SD카드나, 앱 Cache공간에 FileCahce해주는 기능도 있습니다.

상황에 따라 적절하게 개발자가 선택도 가능하며, 자동으로 적절하게 캐시를 합니다.


또 MIT 라이센스라 상업적이나, 개인적인 사용에도 지장이없습니다. 또 Github에서 배포되서 Checkout도 편합니다.


링크 : http://github.com/thest1/LazyList/


MIT Lincense란?


MIT 허가서(영어: MIT License, MIT 라이선스)는 매사추세츠 공과대학교(MIT)을 기원으로 하는 소프트웨어 라이선스 중 가장 대표적인 것이다. X11 License 또는 X License로 표기되기도 한다.


MIT 허가서는 미국의 매사추세츠 공과대학교에서 자기 학교의 소프트웨어 공학도들을 돕기 위해 개발한 허가서이다. MIT 허가서를 따르는 소프트웨어를 개조한 제품을 반드시 오픈 소스로 배포해야 한다는 규정이 없으며, GNU 일반 공중 허가서의 엄격함을 피하려는 사용자들에게 인기가 있다.

MIT 허가서는 GNU 일반 공중 허가서(GPL)등과 달리 카피 레프트는 아니며, 오픈 소스 여부에 관계없이 재사용을 인정하고 있다. BSD 라이선스를 기초로 작성된 BSD계열 라이선스 중의 하나이다. 여러 가지 라이선스 중에서도 MIT 허가서는 매우 제한이 느슨한 라이선스라고 할 수 있다. 이 허가서를 따르는 대표적 소프트웨어로 X 윈도 시스템(X11)이 있다.


출저 : Wikipedia (

http://ko.wikipedia.org/wiki/MIT_%ED%97%88%EA%B0%80%EC%84%9C)





저작자 표시 비영리 동일 조건 변경 허락
신고

[Android] NoThrowThreadPool

ANDROID
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class NoThrowThreadPool extends ThreadPoolExecutor {

    private static final RejectedExecutionHandler defaultHandler = new AdoptPolicy();

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
        setRejectedExecutionHandler(defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);
    }

    public NoThrowThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler);
    }

    public static class AdoptPolicy extends ThreadPoolExecutor.AbortPolicy {

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()).printStackTrace();
        }
    }
}



저작자 표시 비영리 동일 조건 변경 허락
신고

ImageDownloader 사용중 302 status로 IO 오류 발생시

ANDROID

그냥 이것도 저를 위한 메모입니다만, 혹시 저같이 초보인 다른 분들이 헤매실까봐 공개로 해 놓습니다.

NO_ASYNC_TASK일때는 상관 없는데(NO_ASYNC_TASK쓸일은 캐시때문이겠지만...), 

NO_DOWNLOADED_DRAWABLE이나 CORRET 사용시입니다.

페이스북api같이 프로필 사진등을 리다이렉션 해주는 주소로 줄때 이러한일이 발생하는데요.


ImageDownloader클래스의 Bitmap downloadBitmap(String url) 메서드를 수정해 주시면 됩니다.


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
Bitmap downloadBitmap(String url) {
    final int IO_BUFFER_SIZE = 4 * 1024;
 
    // AndroidHttpClient is not allowed to be used from the main thread
    final HttpClient client = (mode == Mode.NO_ASYNC_TASK) ? new DefaultHttpClient() :
        AndroidHttpClient.newInstance("Android");
    final HttpGet getRequest = new HttpGet(url);
 
    try {
        HttpResponse response = client.execute(getRequest);
        final int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 301 || statusCode == 302)
        {
            Header redirect = response.getFirstHeader("Location");
            if (client instanceof AndroidHttpClient)
                ((AndroidHttpClient)client).close();
            return downloadBitmap(redirect.getValue());
        }
        if (statusCode != HttpStatus.SC_OK) {
            Log.w("ImageDownloader", "Error " + statusCode +
                    " while retrieving bitmap from " + url);
            return null;
        }
 
        final HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream inputStream = null;
            try {
                inputStream = entity.getContent();
                // return BitmapFactory.decodeStream(inputStream);
                // Bug on slow connections, fixed in future release.
                return BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                entity.consumeContent();
            }
        }
    } catch (IOException e) {
        getRequest.abort();
        Log.w(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
    } catch (IllegalStateException e) {
        getRequest.abort();
        Log.w(LOG_TAG, "Incorrect URL: " + url);
    } catch (Exception e) {
        getRequest.abort();
        Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
    } finally {
        if ((client instanceof AndroidHttpClient)) {
            ((AndroidHttpClient) client).close();
        }
    }
    return null;
}

강조된 부분이 추가된 부분입니다. (Line 12 ~ 18)

 저도 잘 모르는지라, 질문하셔도 답은 못할 수 있습니다. 


참고 :



저작자 표시 비영리 동일 조건 변경 허락
신고

Activity 애니메이션 XML 모음(?)

ANDROID

안드로이드에서 자주 사용하며 유용하고 이쁜 Activity 전환에 많이 사용하는 전환 애니메이션들 입니다.


사용방법은 추후에 포스팅 하도록 하겠습니다..





slide_in_left.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >

    <translate
        android:duration="200"
        android:fromXDelta="-100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />

</set>




slide_in_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >

    <translate
        android:duration="200"
        android:fromXDelta="100%"
        android:fromYDelta="0%"
        android:toXDelta="0%"
        android:toYDelta="0%" />

</set>




slide_in_top.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="-100%"
        android:toYDelta="0%" />

</set>



slide_out_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="0%"
        android:toYDelta="100%" />

</set>


slide_out_left.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >

    <translate
        android:duration="200"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="-100%"
        android:toYDelta="0%" />

</set>



slide_out_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false" >

    <translate
        android:duration="200"
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="100%"
        android:toYDelta="0%" />

</set>



slide_out_top.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="0%"
        android:toYDelta="-100%" />

</set>



slide_in_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="100%"
        android:toYDelta="0%" />

</set>



압축파일로도 첨부하겠습니다.


res/anim 폴더에 넣고 사용하시면 됩니다.



anim.zip



저작자 표시 비영리 동일 조건 변경 허락
신고

connection still allocated 오류 해결 방법

ANDROID

HttpClient 를 사용중 아래와 같은 오류가 발생 한다.


W/SingleClientConnManager(22006): Invalid use of SingleClientConnManager: connection still allocated


또는



Exception in thread java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated.

Make sure to release the connection before allocating another one.



연결중에 앱이 종료됬다던가 여차저차 기존 HttpClient가 할당되어있을때 발생한다..

그래서 HttpClient를 새롭게 할당하는 부분을 바꿔주어야한다..


아래 함수를 이용한다.


public static DefaultHttpClient getThreadSafeClient()  {

        DefaultHttpClient client = new DefaultHttpClient();
        ClientConnectionManager mgr = client.getConnectionManager();
        HttpParams params = client.getParams();
        client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, 

                mgr.getSchemeRegistry()), params);
        return client;
}


보통 HttpClient = New DefaultHttpClient(); 처럼 Client를 새로 할당해주는 부분을


httpclient = getThreadSafeClient(); 로 바꾸어주면 이미 할당되어 있으면 할당된 Client를 반환해 이후에 문제는 발생하지 않습니다.





위 getThreadSafeClient함수는 http://foo.jasonhudgins.com/2010/03/http-connections-revisited.html에서 발췌하였습니다.

저작자 표시 비영리 동일 조건 변경 허락
신고

Viewholder 사용하기

ANDROID

보통 C/C++와같은 Native 언어에서 필드로 하여, 직접적으로 접근하는 것은 좋은 코드이긴 하나 안드로이드에서는 그렇지 않습니다.



객체에 접근하는 것은 지역 변수에 접근하는 것 보다 매우. 확실히  더 느립니다. 



그러기에 객체에 접근하는걸 Cache화 해야하는데.. 이런기능은 이미 제작되어있습니다..



그런데 별로 설명해주는곳이 없더군요.. 그건 ViewHolder라는 것을 사용하면 됩니다.



이름 그대로 View를 홀더에 꼽는다. 혹은 View에 홀더를 꼽아서 꺼내기 편하게 한다..



 즉. 참조하기 빠르게 미리 꼽아둔다는 겁니다.



제가 사용한 ViewHolder를 보며 예를 들어보겠습니다.


import java.util.ArrayList;

import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
class ViewHolder
{
    ImageView ivThumbnail;
    TextView tvScreenName;
    TextView tvCreatedAt;
    TextView tvText;
}

public class CustomAdapter extends ArrayAdapter<TweetInfo>
{
    private Context mContext;
    private int mResource;
    private ArrayList<TweetInfo> mList;
    private LayoutInflater mInflater;
    public CustomAdapter(Context context, int layoutResource, ArrayList<TweetInfo> objects)
    {
        super(context, layoutResource, objects);
        this.mContext = context;
        this.mResource = layoutResource;
        this.mList = objects;
        this.mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder = null;
        TweetInfo tweet = mList.get(position);
 
        if(convertView == null)
        {
            convertView = View.inflate(mContext, R.layout.lst_view_row, null);                
            holder = new ViewHolder();
            holder.ivThumbnail = (ImageView) convertView.findViewById(R.id.list_view_row_profile_thumbnail);
            holder.tvScreenName = (TextView) convertView.findViewById(R.id.list_view_row_user_screen_name);
            holder.tvCreatedAt = (TextView) convertView.findViewById(R.id.list_view_row_create_at);
            holder.tvText = (TextView) convertView.findViewById(R.id.list_view_row_text);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        
        if (tweet != null) 
        {
            holder.tvScreenName.setText(tweet.getFrom_user());
            holder.tvCreatedAt.setText(tweet.getCreated_at());
            holder.tvText.setText(tweet.getText());
        }
        
  
        return convertView;
    }
}

간단하게 보면


아직 convertView가 캐시화(뷰홀더)에 저장이 안되어있으면, 새롭게 ViewHolder를 선언해 그곳에 꼽아(?) 보관해 줍니다.

다음에 사용할때 바로 멤버로 엑세스가 가능하게끔 접근성을 높여줍니다.


이렇게 사용하고 나면 많은 양의 Row가 잇어도 Listview는 힘들어 하지 않을겁니다.




저의 설명이 매우 부실하기 때문에 [여기][여기]를 참조해주시면 더욱 좋습니다. :)





저작자 표시 비영리 동일 조건 변경 허락
신고

티스토리 툴바