"Project Properties -> Java Build Path -> Order and Export tab" 에 가서 check 'Android Private Libraries' check box.


Ubuntu 12.04 64 bit LTS


* git 을 설치


* server가 실행될 때 항상 실행되도록 Upstart Script 등록

/etc/init/<script name>.conf


<참고>

xxxx.conf : upstart script

xxxx.override : 기존의 xxxx.conf를 override함.


* /etc/init/git-daemon.conf 작성 (git project directory = /work/.prjrepo/)


start on runlevel [2345]                                                                        

stop on runlevel [!2345]                                                                        


expect fork                                                                                     

respawn                                                                                         


exec /usr/bin/git daemon --user=gitro --group=gitro --reuseaddr --base-path=/work/.prjrepo/ /work/.prjrepo/


* export하고자 하는 git repository안에 magic file인 git-daemon-export-ok 파일 생성 (size 0인 dummy file - 그냥 touch로 생성하면 된다.)


* client에서 test.

git clone git://<host>/<project>

<9418 포트 사용>

'Domain > Linux' 카테고리의 다른 글

[Linux] mmap and memory...  (0) 2013.10.07
CoW(Copy on Write) on ARM  (0) 2013.09.26
atime 대신에 strictatime을 사용하자!  (0) 2013.05.31
[Shell] Variable Name Expansion  (0) 2013.03.28
[Linux][Shell] Cleaning PATH environment variable.  (0) 2011.09.15

Ubuntu의 경우 default mount option이 'relatime'으로 되어 있는데, 이것을 바꾸기 위해서 "mount -o remount,atime,xxxx" 식으로 해도 relatime 에서 atime으로 mount상태가 바뀌지 않는다.

대신 strictatime을 사용하면, 정상적으로 원하는 형태로 mount할 수 있다.

(mount의 man page에 상세하게 설명이 나와있긴 하나... atime이상 동작하지 않는다는 설명은 찾을 수 없었다.)


요점은 atime 대신 strictatime을 사용하라!

특정 코드 구간이 수행되는 시간을 측정해야 할 경우가 종종 생기는데, 대부분 아래와 같은 방법을 사용한다. (ex. Java)

 

long tm = System.currentTimeMillis();
< do something >
tm = System.currentTimeMillies() - tm;
System.out.println("Time : " + tm);
그렇지만, 약간만 응용을 하면 아~주~ 조금이지만, 위의 코드를 더 간단하게 만들 수 있다.

long tm = -System.currentTimeMillis();
< do something >
tm += System.currentTimeMillis();
System.out.println("Time : " + tm);

어떤가? ^_^


Variable operator

Action 

Description 

${varname}

Nonambiguous variable substitution 

Simple variable substitution occurs with the value of varname being substituted

${varname:=value}

Assign a default value for the variable if a value does not exist.

If varname does not have a value or is set to null, then varname is set to value.

Varname is then substituted in the statement.

${varname:+value} 

Utilize value if varname is set 

If the variable, varname, contains a value and is not null, then the alternate value, value, is substituted instead of the value of the variable varname. Otherwise nothing is substituted.

${varname:-value} 

Assign a temporary default value for a variable if one does not exist 

If the variable, varname, contains a value and is not null, then it is substituted; otherwise the value, value, is substituted but is not assigned to varname. (different from = operator)

${varname:?value} 

Issue an error message if the value of variable is not set to any value. 

If the variable, varname, containsa value and is not null, then it is substituted; otherwise an error message containing the value, value, is printed and the Shell exits.

${#varname}
(Korn and Bash only) 

Return the length of the value contains in varname or the number of positional parameters.

If varname is set, the length of the value of varname is returned. If the special variable * or @ is used as varname then the number of positional parameters are returned. 

${varname#pattern}

${varname##pattern}

(Korn and Bash only) 

Substitue varname with pattern removed from the beginning of varname .

If the pattern matches the begining of varname, then pattern is removed from varname. If the # form is used, then the shortest match is removed. If the ## form is used, then the longest match is replaced. 

${varname%pattern}

${varname%%pattern}

(Korn and Bash only) 

Substitute varname with pattern removed from the end of varname. 

If the pattern matches the end of varname, then pattern is removed from varname. If the % form is used, then the shortest match is removed. If the %% form is used, then the longest match is replaced. 

${#arrayname[*]}
(Korn only) 

Substitute the number of elements in the array. 

The number of elements in the array arrayname is substituted. 


<From : UNIX Shell Programming, FOURTH EDITION, LOWELL JAY ARTHUR, TED BURNS - WILEY COMPUTER PUBLISHING>

Sometimes FragmentManager destroys and re-instantiates Fragment without any notification by framework's behavior.

Important point here is that default Constructor is used to re-instantiate Fragment.

In this case, without saving and restoring run-time state of Fragment, it looses all of it's state.

This is exactly same with Activity.

But, in terms of Activity, user can know and control when the Activity is destroyed and recreated.

So, in case of Activity, this issue is not big problem.


Therefore, followings should be considered to design Fragment.

- use ONLY default constructor. (FragmentManager uses only default constructor.)

- should NOT have any not-parcelable- run-time data.


But, sometimes, Fragment may need to have not-parcelable-run-time data.

In this case, using Activity can be good choice.

That is, let owner Activity have the data and access it by using getActivity() method.


FragmentPagerAdapter is very useful and easy-to-use.
But, there is one point to keep it mind when using it.
See below codes from FragmentPagerAdapter.java

    @Override
    public Object instantiateItem(View container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), position);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + position + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), position));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setStartDeferred(true);
        }

        return fragment;
    }

Usually, FragmentPagerAdapter is used with ViewPager. In this case, variable container is reference of ViewPager.

Developer who are familiar with normal AdapterView, may try to change FragmentPagerAdapter by using setAdapter interface of ViewPager without doing something else to ViewPager.

But, in this case, as you can see from above code, instantiateItem function reuses previous Fragment instance because even if FragmentPagerAdapter is changed, ViewPager is same. So, fragment name getting from makeFragmentName function returns same value.

And that is NOT expected result at normal AdatperView.


[ Android ICS ]

PatternMatcher is used for pathPattern at IntentFilter

But, PatternMatcher's algorithm is quite strange to me.

Here is algorithm of Android PatternMatcher.


If there is 'next character' of '.*' pattern in the middle of string, PatternMatcher stops loop at that point.

(See PatternMatcher.java of Android framework.)


Ex.

string  : "this is a my attachment"

pattern : ".*att.*".

Android PatternMatcher enter loop to match '.*' pattern until meet the next character of pattern

(at this example, 'a')

So, '.*' matching loop stops at index 8 - 'a' between 'is' and 'my'.

Therefore result of this match returns 'false'.


Quite strange, isn't it.

To workaround this - actually reduce possibility - developer should use annoying stupid pathPattern.


Ex.

Goal : Matching uri path which includes 'message'.

<intent-filter>

...

<data android:pathPattern=".*message.*" />

<data android:pathPattern=".*m.*message.*" />

<data android:pathPattern=".*m.*m.*message.*" />

<data android:pathPattern=".*m.*m.*m.*message.*" />

<data android:pathPattern=".*m.*m.*m.*m.*message.*" />

...

</intent-filter>


This is especially issued when matching with custom file extention.


Ex.

Goal : Matching file which extention is 'myextention'.


Below filter doesn't work as expected because of issue described above.

(Ex. "sample.test.myextention" doesn't match by PatternMatcher.)

<intent-filter>

...

<data android:pathPattern=".*\\.myextention" />

...

</intent-filter>


So, like above, stupid-dirty filter should be used as follows.

<intent-filter>

...

<data android:pathPattern=".*\\.myextention" />

<data android:pathPattern=".*\\..*\\.myextention"/>

<data android:pathPattern=".*\\..*\\..*\\.myextention"/>

<data android:pathPattern=".*\\..*\\..*\\..*\\.myextention"/>

...

</intent-filter>


Done. :-)

Height of status bar can be read by following way. (can be found easily by Googling - ex. stack-overflow)


Rect rect= new Rect();

Window window= activity.getWindow();

window.getDecorView().getWindowVisibleDisplayFrame(rect);

return rect.top;


But, even after hiding status bar by adding LayoutParams.FLAG_FULLSCREEN at onCreate() or onResume(), height of status bar read by above way, may be still invalid (Not 0).

(I didn't analyze deeply about WindowManager. So, I'm not sure about root cause - due to animation effect??? or something else???)

To workaround this issue, the best place to read height of status bar - hidden or shown - is onWindowFocusedChanged().

Reading height of status bar at the first call of onWindowFocusedChanged() gives exact(expected) value based on my experience.

And then, this value can be reused afterward.


Sometimes developer may be faced with below log message with extremely-slow-scrolling of List.


Log includes "Window is full: requested allocation 2195889 bytes, free space 2096720 bytes, window size 2097152 bytes"


Most case of this kind of issue can be seen when SQLite DB has blob-type field whose data is quite big, and Cursor that includes this field is used at Aadapter.

In this case, Cursor easily exceeds it's maximum Window size (at Android 4.0.3, this value is about 2 MB).

After reaching to maximum Window size, Cursor need to handle Window, and at worse, field size is quite big.
So, whenever move to another row of Cursor, Cursor should handle quite complex disk operation.

So, at this moment, scrolling list becomes very very slow.


To avoid this, main Cursor of Adapter would better not to have big-size field of DB Table.

Instead of it, try to read from DB whenever the field value is demanded.


Then, average time for scrolling list may be increased. But, even at worst cases, list can show reasonable scrolling performance.


+ Recent posts