среда, 9 ноября 2016 г.

Mercurial sucks

Intro


There are a lot of strange things in the project which I am working at.
One of it is Mercurial as VCS in 2016, and a lot of hooks.

Some rules:
1. You should install on you PC Postgres, python, etc.
2. To do single commit on local PC you will be faced with local commit hooks, that will download new Postgres database, check your permissions, and allow or not your current changes to saved.. (Of course, all hooks are disabled for people who set it up!) Single commit can be 10min waiting. Pull/push 5-30min.
3. Not enough? any merge between branches is not allowed. Only to/from default, no shelve, nothing, only 2 commands commit and merge to/from default.
4. Made mistake in commit template - you will  not be able to save your changes for current branch... you should create the new one branch and committing one by one move all changes...

So, What can we do with this shit?

Convert Mercurial to Git, and use git at least on local PC!

Short project overview that can be used for converting from Mercurial to Git



0. git-remote-hg

My winner. It adds git plugin, so you can work with a git repository, and mercurial is "remote" repository.
Push/Pull works. Also, fast-forward should be disabled because mercurial so stupid.
https://github.com/felipec/git-remote-hg


1. fast-export

Convert mercurial repository to git. Really nice tool.
https://github.com/frej/fast-export


2. git-hg

Use git like commands to work with a mercurial repository. Wrapper for fast-export.
Does not work with my git workflow.
https://github.com/offbytwo/git-hg


3. gitifyhg

Better then prev one, you can use git commands.
It keeps a local copy of a mercurial repository and does same commands to both repositories.
Have problems with fast-forward commits.
https://github.com/buchuki/gitifyhg

4. Others

https://github.com/glandium/git-cinnabar
https://github.com/git/git/tree/8d530c4d64ffcc853889f7b385f554d53db375ed/contrib/remote-helpers
https://github.com/cosmin/git-hg
https://github.com/abourget/git-hg-again
https://github.com/rfk/git-remote-hg
https://github.com/nwgh/git-hg
https://github.com/msysgit/msysgit/wiki/Guide-to-git-remote-hg


About "git-remote-hg" set up in my project

1. install tools

wget https://raw.github.com/felipec/git-remote-hg/master/git-remote-hg -O ~/bin/git-remote-hg
chmod +x ~/bin/git-remote-hg

 

 2. clone repository

git clone "hg::ssh://user@example.com/Project"

 

 3. configure git


project/.git/config

[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = hg::ssh://user@example.com/Proejct
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[user]
        name = user.name
        email = unknown
[merge]
        ff = false


project/.git/hooks/commit-msg

#!/bin/sh
NAME=$(git branch | grep '*' | sed 's/* //' | grep -o '[0-9]\+')
echo "\n\nrefs #$NAME\n`cat $1`\n" > "$1"


project/.git/hooks/prepare-commit-msg

#!/bin/sh

addMyBranchName() {
  # Get name of current branch
  NAME=$(git branch | grep '*' | sed 's/* //' | grep -o '[0-9]\+')
 
  # First blank line is title, second is break for body, third is start of body
  BODY=`cut -d \| -f 6 $1 | grep -v -E .\+ -n | cut -d ':' -f1 | sed '3q;d'`

  # Put in string "(branch_name/): " at start of commit message body.
  # For templates with commit bodies
  if test ! -z $BODY; then
    awk 'NR=='$BODY'{$0="refs #'$NAME'"}1;' $1 > tmp_msg && mv tmp_msg "$1"
  else
    echo "\n\nrefs #$NAME\n`cat $1`\n" > "$1"
  fi
}

# You might need to consider squashes
case "$2,$3" in
  # Commits that already have a message
  commit,?*)
  ;;

  # Messages are one line messages you decide how to handle
  message,)
  ;;

  # Merge commits
  merge,)
    # Comments out the "Conflicts:" part of a merge commit.
    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1"
  ;;

  # Non-merges with no prior messages
  *)
    addMyBranchName $1
  ;;
esac

среда, 4 декабря 2013 г.

WebView cause memory leak.


WebView problems description:

1. WebView cause memory leak in Android core and high CPU usage if Javascript enabled.

Bug reports on Android bug tracker

How to reproduce?

  • Create test project with WebView
  • Load some URL few times with WebView.loadUrl()
  • see memory leak
Same problem here with example application

Full Solution - not found.

It's official bug.

Solution (not solution, but works)

Disable javascript support at all
webView.setJavaScriptEnabled(false)

Partial solution 1

call the onPause / onResume on the webview to reduce CPU usage
  • CPU usage decreased
  • Memory leak present
code:
Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(webView, (Object[]) null);
[Detail on Android bug tracker][link 3]

Partial solution 2

  • loadDataWithBaseURL
WebView.loadDataWithBaseURL(url,data,"text/html","UTF-8",url);
Fine for static page, but not for site in Internet.

Partial solution 3

Disable all...
 mWebView.getSettings().setAppCacheEnabled(false);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mWebView.getSettings().setDatabaseEnabled(false);
mWebView.getSettings().setDomStorageEnabled(false);
mWebView.getSettings().setGeolocationEnabled(false);
mWebView.getSettings().setPluginsEnabled(false);
mWebView.getSettings().setSaveFormData(false);
mWebView.getSettings().setSavePassword(false);
clean up, destroy, create new WebView
 mWebView.removeAllViews();
mWebView.destroyDrawingCache();
mWebView.clearCache(true);
mWebView.clearHistory();
mWebView.freeMemory();
mWebView.destroy();
mWebView = null;
Memory leak present

2. OutOfMemoryException

See problem 1 and http://stackoverflow.com/questions/6497780/webview-outofmemoryexception

3. WebView causes memory leak - leaks the parent Activity

Starting an activity with a WebView, then destroying that activity (hitting back) and getting a heap dump shows that there are uncleaned up references that cause the activity to stay in memory (leak).
I use a WebView to display some internet content on one of our app's Activities. The problem is that when the user switches out of this activity, WebView's threads keep running!

среда, 10 октября 2012 г.

#ifdef for android project

1. Плагин для eclipse


Antenna

2. Под проекты.


Общий код вынести в библиотеку.
Создать новые проекты и использовать библиотеку.

3. Системы автоматической сборки.


maven, ant


Links



четверг, 19 июля 2012 г.

Отключить кнопку HOME

Гугл не рекомендует этого делать. Пользователь всегда должен иметь возможность выйти из приложения.
Но иногда нужно.

Рабочее решение
Логичный шаг получить событие кнопки.


public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_HOME) {
     // делаем что-то полезное :)
     return true;
   } else {
     return super.onKeyDown(keyCode, event);
   }
 }


Магия, без которой не работает

public void onAttachedToWindow() {

this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);

super.onAttachedToWindow();

}




Ссылки
http://stackoverflow.com/questions/6693896/home-key-press-event-listener
http://stackoverflow.com/questions/2079691/overriding-the-home-button-how-do-i-get-rid-of-the-choice
http://stackoverflow.com/questions/4783960/call-method-when-home-button-pressed-on-android?rq=1

Две acvivity в Launcher

Две активити в ланчере. Одна для приложения, другая для настроек.

  <application
        android:name=".APP"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
       
        <activity
            android:name=".activity.Main"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

        <activity
            android:name=".activity.Preferences"
            android:label="@string/set_preferences"
            android:noHistory="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  </application>

ссылки
http://stackoverflow.com/questions/8927315/two-launcher-activities

Разные Android Context

Какая разница между context.




public class MyActivity extends Activity { 
  public void method() { 
    mContext = this; // since Activity extends Context 
    mContext = getApplicationContext(); 
    mContext = getBaseContext(); 
  } 
}



Если сделать Toast разными context, то:

Умрет вместе с активити.
Toast.makeText(this, "Text", Toast.LENGTH_SHORT).show();

Умрет вместе с приложением
Toast.makeText(getApplicationContext(), "SD card not found", Toast.LENGTH_SHORT).show();

Будет виден даже после завершения приложения.
Toast.makeText(getBaseContext(), "SD card not found", Toast.LENGTH_SHORT).show();

Обсуждение
http://stackoverflow.com/questions/1026973/android-whats-the-difference-between-the-various-methods-to-get-a-context

Поиск USB флешки


Рабочий вариант

Задача.
Поиск файлов на USB в специальной папке
FOLDER_NAME - имя папки
searchFileInFolder - функция проверке на наличие нужной информации в найденной папке.

Возвращает первую папку, с
private String searchSMILFileInMNT() {
Log.d(TAG,"[mnt] Scan start");

File mnt = new File("/mnt/");
File mntFileList[] = mnt.listFiles();

for(int i=0; i< mntFileList.length; i++){
File f = mntFileList[i];
Log.d(TAG,"[mnt] Scan dir "+f.getAbsolutePath());
if(f.isDirectory() && f.canRead()){
File smilDir = new File(f.getAbsolutePath()+File.separator+FOLDER_NAME);
String SDcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();

if(smilDir.isDirectory() && smilDir.canRead() && (!smilDir.getAbsolutePath().equals(SDcardPath))){
String name = searchFileInFolder(smilDir.getAbsolutePath());
if(name!=null){
Log.d(TAG,"[mnt] Found file "+name);
return smilDir.getAbsolutePath()+File.separator + name;
}

}
}

}
Log.d(TAG,"[mnt] mothing found");
return null;
}

Как получить список всех примонтированых  USB устройств?