分類
Jenkins

git plugin error on Jenkins : Couldn't find any revision to build. Verify the repository and branch configuration for this job.

Description :
建立完 git repo 並在jenkins新增相對應的job, 執行”馬上建置”, 在jenkins console output顯示的訊息如下

...
ERROR: Couldn't find any revision to build. Verify the repository and branch configuration for this job.
Finished: FAILURE

該錯誤目前只出現在建立完 git repo, 但未commit的情況下, 事實上開啟Terminal, 移動到git repo, 輸入git log會出現以下訊息

fatal: bad default revision 'HEAD'

只要有git commit過後, 即可解決
 
Solution :
Step 1.
新增一個檔案, 檔案內容形式不拘 e.g. ReadMe
 
Step 2.
git add ReadMe
 
Step 3.
git commit
 

分類
Script

How to auto login as root by expect script

We use “expect” to auto login as root, reference here(expect)

 
1.  Install “expect” on your machine

sudo apt-get install expect

 
2. write expect script(auto_login_root.sh)

#!/usr/bin/expect
set password "here_is_your_root_password"
spawn sudo -i
send "$password\r"
interact

Note :  command reference
 
3. execute expect script

expect auto_login_root.sh

 

分類
Jenkins

git plugin error on Jenkins : Permission denied (publickey).

Description :
安裝 git plugin 之後, 建立專案->組態->原始碼管理 -> Git -> Repository URL 並設定以下內容

ssh://username@xxx.xxx.xxx.xxx:port/absolute_path.git

 
Error :
此 error message 出現在 Repository URL下方

Failed to connect to repository : Command "/usr/bin/git -c core.askpass=true ls-remote -h ssh://username@xxx.xxx.xxx.xxx:port/absolute_path.git HEAD" returned status code 128:
stdout:
stderr: Permission denied (publickey).
fatal: The remote end hung up unexpectedly

 
Solution :
Step 1.
首先讓另一台主機(s2)使用ssh成功登入到jenkins主機上,並在jenkins主機的~/.ssh/authorized_keys 加入s2的id_rsa.pub
 
Step 2.
複製s2的id_rsa檔案貼到jenkins主機的家目錄任意資料夾中(e.g. /home/username/server/id_rsa_files/id_rsa )此rsa檔案將被使用在Step 3.
 
Step 3.
在jenkins主機安裝 Credentials plugin 並使用 Credentials plugin 建立一個 Credentials 內容如下
Kind : SSH Username with private key,
Scope : Global
Username : (任意)
Description :  (任意)
Private key :  From a file on Jenkins master (選擇Step 2.複製到jenkins主機上的s2 id_rsa檔(/home/username/server/id_rsa_files/id_rsa))
 
Step 4.
在原始碼管理 -> Git -> Repository URL 下方的 Credentials 內容設定為Step 3. 新增的Credentials
 
Step 5.
編輯 /etc/ssh/sshd_config 加入新的port e.g.

# Package generated configuration file
# See the sshd_config(5) manpage for details
# What ports, IPs and protocols we listen for
Port 22
Port 23
...

Port 23 即是新的Port,會使用在ssh://username@xxx.xxx.xxx.xxx:port/absolute_path.git 的 port
 
Step 6.
將Step 5.新增的Port number 設定到Repository URL中

ssh://username@xxx.xxx.xxx.xxx:23/absolute_path.git

完成後Error訊息就會消失
 
 
Note :
1.Permission denied的原因有很多, 首先從git repo建立者和jenkins使用者關係找起, 將2者config設定一致, 也在jenkins使用者中加入ssh public key, 無效
2.設定jenkins->設定系統-> Git plugin -> Global Config user.name Value 和 Global Config user.email Value 設定與git repo建立者相同, 無效
3.使用Credentials plugin建立jenkins主機的credential(類似Step 3. 但其中的Private key設定為jenkins本機的id_rsa)並設定在 原始碼管理 -> Git -> Repository URL 中 也是無效
4.在Repository URL的Port Number設定也有關係, 若不依照 Step 5.建立新Port, Permission denied還是無解

分類
Design Pattern

使用Simple Factory Pattern替換多建構式

Simple Factory Pattern:

提供產生物件的方法, 而無須關注實作內容, 其物件類型可為interface, abstract class, class

 
當類別內有多建構式存在且每個建構式無法清楚的說明其用途時, 可使用Simple Factory代替建構式, 在SimpleFactory中以清楚的方法名稱說明建構式的用途
這是我在專案遇到的情況, 我必須寫出1個Dialog, 此Dialog的元件在不同的情況下會有不同的組合, 如在A情況此dialog只有1個按鈕, 在B情況會有2個按鈕
一開始考慮使用建構式來決定產生何種dialog

package com.foxx.simplefactory;
import android.app.Dialog;
import android.content.Context;
import android.widget.Button;
import android.widget.TextView;
public class CustomDialog extends Dialog
{
    private String mDescription;
    private TextView mUpTextView;
    private TextView mDownTextView;
    private Button mUpButton;
    private Button mDownButton;
    /**
     * Used in one button
     */
    public CustomDialog(Context context, Button upButton) {
        super(context);
    }
    /**
     * Used in two button
     */
    public CustomDialog(Context context, Button upButton, Button downButton) {
        super(context);
    }
    /**
     * Used in one button and one description
     */
    public CustomDialog(Context context, Button upButton, String description) {
        super(context);
    }
}

 
CustomDialog的使用者除了從建構式的參數以及註解外, 無法了解建構式的使用方式(意圖), 為了解決這個情況我試著引入Simple Factory來修改

package com.foxx.simplefactory;
import android.content.Context;
import android.widget.Button;
public class CustomDialogFactory
{
    public static CustomDialog createOneButtonDialog(Context context, Button upButton)
    {
        return new CustomDialog(context, upButton);
    }
    public static CustomDialog createTwoButtonDialog(Context context, Button upButton,
            Button downButton)
    {
        return new CustomDialog(context, upButton, downButton);
    }
    public static CustomDialog createOneButtonOneDescriptionDialog(Context context,
            Button upButton, String description)
    {
        return new CustomDialog(context, upButton, description);
    }
}

 
使用者可根據Simple Factory的方法名稱選擇建立CustomDialog物件

package com.foxx.simplefactory;
import com.example.simplefactory.R;
import com.foxx.factorymethod.*;
public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CustomDialog oneButtonDialog = CustomDialogFactory.createOneButtonDialog(context, upButton);
        CustomDialog twoButtonDialog = CustomDialogFactory.createTwoButtonDialog(context, upButton, downButton);
        CustomDialog oneButtonOneDescriptionDialog =
        CustomDialogFactory.createOneButtonOneDescriptionDialog(context, upButton, description);
    }
}

 

Class Diagram

simplefactory_classdiagram
 

分類
Uncategorized

How to run Shell Script in Eclipse

Description :

Use eclipse to run shell script file
 

Step :

Open eclipse ->Run -> External tools -> External Tools Configurations… -> select Program ->
click “new launch configuration” -> select your .sh file at “Location” -> select your .sh file root directoy at “Working Directory” ->
click “Apply” -> click “Run” -> now you can see result at eclipse console

分類
CloneZilla

使用 CloneZilla 複製 HDD(大容量1TG) 到 SSD(小容量240G) on ubuntu

Target

使用 CloneZilla 複製 HDD(大容量1TG) 到 SSD(小容量240G) on ubuntu
 

System Requirements

ubuntu 12.04
clonezilla 20130703-raring-i386
Gparted
 

Description

HDD(總容量1TG)是原運作硬碟, 磁碟內容分為3個分割區
根目錄(/)(分割空間200G, 使用空間20G), 家目錄(/home)(分割空間780G, 使用空間120G), swap空間20G
而SSD(總容量240G)是用來替換原運作硬碟, 無任何空間分割
 

Error Handling

當來源碟(HDD 1TG)容量大於目的碟(SSD 240G), 複製時會出現目的碟容量不足錯誤訊息
這時候就需要一些trick way來避開, 首先必須滿足條件是HDD的”分割空間”必須小於SSD的總空間
如在Description提到HDD總分割空間為 200G(根目錄) + 780G(家目錄) = 980G 是大於 SSD 的分割空間(240G), 會造成目的碟容量不足
待會在Step 2.將HDD的分割空間縮小, 使得HDD總分割空間小於SSD
 

Setup

Step 1.
先對原運作硬碟HDD備份吧, 為了避免對原運作硬碟造成影響, 最好能夠準備一顆和原運作硬碟總容量相同大小的測試用硬碟, 再把原運作硬碟完全複製到測試用硬碟,
之後的動作全部使用測試用硬碟來執行
 
Step 2.
使用Gparted對HDD縮減分割空間, 以HDD的根目錄為例, 雖然分割空間有200G, 但使用空間只有20G, 所以可將根目錄的分割空間縮到20G, 讓分割空間和使用空間幾乎相同
對HDD的家目錄作相同的動作, 縮減分割空間到120G
Note :  在本步驟就是調整HDD的分割空間使其小於SSD的總空間
 
Step 3.
使用Gparted對SSD作分割空間的動作, 先在SSD切割一塊空間(大於20G即可), 此空間就是為了能完全複製HDD的根目錄
再切割另一塊空間(大於120G), 為了複製HDD的家目錄, 注意以上空間切割時可順便作貼齊的動作, 檔案格式選擇ext4
 
Step 4.
先複製HDD根目錄到SSD上吧, 使用CloneZilla選擇
device – device 處理整顆硬碟或部份分割區的直接複製 -> 專家模式 -> 複製本機分割區到本機分割區 ->
選擇來源分割區(注意此來源分割區必須選擇HDD的根目錄) -> 選擇目的分割區(注意此目的分割區必須選擇SSD的第一塊分割空間(大於20G)) ->
設定的進階參數(勾選”略去檢查目的碟空間是否夠大”) -> 略去檢查與修正來源分割區 -> -k 不要在目的碟的開機磁區產生分割區的分割表 ->
完成
Note : 完成後即可使用SSD嘗試開機, 可正常開機但無法登入, 因為HDD的家目錄還未複製到SSD上
 
Step 5.
再複製HDD的家目錄到SSD上, 使用CloneZilla選擇
device – device 處理整顆硬碟或部份分割區的直接複製 -> 專家模式 -> 複製本機分割區到本機分割區 ->
選擇來源分割區(注意此來源分割區必須選擇HDD的家目錄) -> 選擇目的分割區(注意此目的分割區必須選擇SSD的第二塊分割空間(大於120G)) ->
設定的進階參數(勾選”略去檢查目的碟空間是否夠大”) -> 略去檢查與修正來源分割區 -> -k 不要在目的碟的開機磁區產生分割區的分割表 ->
完成
Note 1. 完成後即可使用SSD嘗試開機, 可正常開機且登入, 所有的檔案都和HDD相同
Note 2. 完成後記得再去啟動 SSD 的 TRIM 功能
 

Review

事實上完成複製的條件在於先調整HDD分割空間使其小於SSD容量, 以避開容量不足的錯誤訊息, 只要能夠達到這點
無論是HDD -> SSD, SSD -> HDD 都能複製, 在windows系統也可成功複製

分類
Eclipse error

Eclipse error : Eclipse hangs at the Android SDK Content Loader(0%)

Description : Launch eclipse ide andstucked, “Android SDK Content Loader (0%)” show at of left-bottom dialog
 
Root Cause : Unknow
 
Solution :

cd workspace/.metadata/.plugins/org.eclipse.core.resources/.projects
rm -rf *

ps : Projects won’t be lost but Some projects will confuse need to rebuild
 
Note :
Solution1. Remove ~/.android/cache and ~/.android/ddms.cfg not worked for me !!!
Solution2. Eclipse -> Project -> Build Automatically -> uncheck this option -> restart eclipse fail !!!

分類
Uncategorized

Run "About" sample on Alljoyn for linux version

參考官網步驟
以下為紀錄成功過程

Export path

1. Open terminal and move to root dir
Note: In my case, root dir name is alljoyn-14.12.00a-src
 
2. Terminal type

export AJ_ROOT=`pwd`

 
 
3. Terminal type

export TARGET_CPU=x86

Note: <TARGET CPU> can be either x86_64, x86, or whatever value you set for “CPU=” when running SCons.
value of TARGET CPU must matchas path, e.g.
/alljoyn-14.12.00a-src/build/linux/x86_64/  or  /alljoyn-14.12.00a-src/build/linux/x86/
 
4. Terminal type

export LD_LIBRARY_PATH=$AJ_ROOT/build/linux/$TARGET_CPU/debug/dist/cpp/lib:$LD_LIBRARY_PATH

 
 

Run the AboutService Sample App

1. In root of dir(alljoyn-14.12.00a-src), type

$AJ_ROOT/build/linux/$TARGET_CPU/debug/dist/cpp/bin/samples/AboutService

Note: some message will print on terminal e.g.

BusAttachment started.
   0.037 ****** ERROR NETWORK                   common/os/posix/Socket.cc:346 | Binding (sockfd = 59) to 0.0.0.0 9955: 98 - Address already in use: ER_OS_ERROR
BusAttachment connect succeeded. BusName :AVq3OlHG.2
AboutObj Announce Succeeded.
   0.041 ****** ERROR NETWORK                   common/os/posix/Socket.cc:346 | Binding (sockfd = 58) to 0.0.0.0 9955: 98 - Address already in use: ER_OS_ERROR
   1.863 ****** ERROR NETWORK iodisp2_0         common/os/posix/Socket.cc:463 | Shutdown socket (sockfd = 11): 107 - Transport endpoint is not connected: ER_OS_ERROR

it will show message when client connects.
 

Run the AboutClient Sample App

1. In root of dir(alljoyn-14.12.00a-src), type

$AJ_ROOT/build/linux/$TARGET_CPU/debug/dist/cpp/bin/samples/AboutClient

Note: terminal print message e.g.

BusAttachment started.
BusAttachment connect succeeded.
WhoImplements called.
*********************************************************************************
Announce signal discovered
	From bus :R8gNQJgr.2
	About version 1
	SessionPort 900
	ObjectDescription:
		/example/path
			com.example.about.feature.interface.sample
	AboutData:
		Key: AppId	01 b3 ba 14 1e 82 11 e4 86 51 d1 56 1d 5d 46 b0
		Key: DefaultLanguage	en
		Key: DeviceId	93c06771-c725-48c2-b1ff-6a2a59d445b8
		Key: ModelNumber	123456
		Key: AppName	Application
		Key: DeviceName	My Device Name
		Key: Manufacturer	Manufacturer
*********************************************************************************
...
Calling /example/path/com.example.about.feature.interface.sample
Echo method reply: ECHO Echo echo...

 
2. AboutServer will print message e.g.

...
Session Joined SessionId = 3156666061
Echo method called: ECHO Echo echo...

 

分類
Uncategorized

Build AllJoyn framework for linux version

參考官網提供基本流程
以下是紀錄成功的流程
 

1. Setup

1-1. Build tools and libs

sudo apt-get install build-essential libgtk2.0-dev libssl-dev xsltproc ia32-libs libxml2-dev

 
 
1-2. Install Python v2.6/2.7 (Python v3.0 is not compatible and will cause errors)

sudo apt-get install python

Note:測試python 2.6.5, 2.7.3皆可, 若已安裝過則省略
 
1-3. Install SCons v2.0

sudo apt-get install scons

 
1-4. OpenSSL

sudo apt-get install libssl-dev

Note:似乎和Build tools and libs 有重複
 
1-5. Download the AllJoyn Source zip and extract source. The tree should look like below. Note, extra directories may exist.

root-source-dir/
  core/
      alljoyn/
      ajtcl/
  services/
      base/
      base_tcl/

Note: download source zip 選擇alljoyn-14.12.00a-src.tar.gz 解壓縮完會產生 alljoyn-14.12.00a-src 目錄,目錄內容如下

alljoyn_c     alljoyn_java  alljoyn_objc   build_core  common        README.md   SConstruct
alljoyn_core  alljoyn_js    alljoyn_unity  build.xml   manifest.txt  README.txt  services

除了選擇alljoyn-14.12.00a-src.tar.gz 以外還可使用git clone的方式來下載 source code 參考這裡, 但未測試

2. Build Sample

2-1. 開啟終端機移動到 alljoyn-14.12.00a-src 目錄中並輸入

scons BINDINGS=cpp WS=off BT=off ICE=off

terminal會出現一連串build step, 如下

scons: Reading SConscript files ...
Building bindings: cpp
Building services:
BULLSEYE_BIN not specified
GTEST_DIR not specified skipping common unit test build
BULLSEYE_BIN not specified
GTEST_DIR not specified skipping About Service unit test build
GTEST_DIR not specified skipping alljoyn_core unit test build
scons: warning: Ignoring missing SConscript 'build/linux/x86_64/debug/obj/services/about/SConscript'
File "/home/rcserver/projects/jellyfish/alljoyn-14.12.00a-src/alljoyn_core/samples/eventaction/SConscript", line 35, in <module>
scons: done reading SConscript files.
scons: Building targets ...
Install file: "alljoyn_core/docs/README.linux.txt" as "build/linux/x86_64/debug/dist/README.txt"
...

Note: 完成後會產生build資料夾, 後續 run sample 動作都與此有關
 
最後輸入

SERVICES="about,notification,controlpanel,config,onboarding,sample_apps"

 
 

分類
Uncategorized

AlertDialog + MultiChoiceItems

1.MainActivity.java

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity
{
    private Button mShowAlertDialog;
    private TextView mShowSelectedItemsOfAlertDialog;
    private String[] mItemsOfAlertDialog;
    private boolean[] mSelectedItems;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mItemsOfAlertDialog = getResources().getStringArray(R.array.dialog_items);
        mSelectedItems = new boolean[mItemsOfAlertDialog.length];
        mShowAlertDialog = (Button) findViewById(R.id.show_alert_dialog);
        mShowSelectedItemsOfAlertDialog = (TextView) findViewById(R.id.show_selected_items);
        mShowAlertDialog.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v)
            {
                showAlertDialog();
            }
        });
    }
    private void showAlertDialog()
    {
        Resources resources = getResources();
        AlertDialog.Builder ab = new AlertDialog.Builder(this);
        ab.setTitle(resources.getString(R.string.alert_dialog_name));
        ab.setMultiChoiceItems(R.array.dialog_items, mSelectedItems,
                new MultiChoiceClickListener());
        ab.setPositiveButton(resources.getString(R.string.ok),
                new ClickListenerForPositiveButton());
        ab.setNegativeButton(resources.getString(R.string.exit),
                new ClickListenerForNegativeButton());
        ab.show();
    }
    private final class ClickListenerForNegativeButton implements OnClickListener
    {
        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            dialog.dismiss();
        }
    }
    private final class ClickListenerForPositiveButton implements OnClickListener
    {
        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            String selectedItems = "";
            for (int i = 0; i < mSelectedItems.length; ++i) {
                if (mSelectedItems[i]) {
                    selectedItems = selectedItems + mItemsOfAlertDialog[i] + "\n";
                }
            }
            mShowSelectedItemsOfAlertDialog.setText(getResources().getString(
                    R.string.selected_items)
                    + "\n" + selectedItems);
            dialog.dismiss();
        }
    }
    private final class MultiChoiceClickListener implements OnMultiChoiceClickListener
    {
        @Override
        public void onClick(DialogInterface dialog, int which, boolean isChecked)
        {
            mSelectedItems[which] = isChecked;
        }
    }
}

Note:
showAlertDialog(), 其中setMultiChoiceItems()就是設定為Multi choice的重點, 第一個參數mItemsOfAlertDialog為soft coding帶入dialog item, dialog item定義在xml  中 如下
/res/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array
        name="dialog_items">
        <item>item1</item>
        <item>item2</item>
        <item>item3</item>
        <item>item4</item>
        <item>item5</item>
    </string-array>
</resources>

第2個參數 mSelectedItems 則是代表dialog item是否被選中
MultiChoiceClickListener類別則為監聽alertdialog中item被選中的事件,其實比較方便的寫法是直接建立匿名類別,但如此一來showAlertDialog()長度會被大幅增加, 可讀性降低
ClickListenerForNegativeButton類別則為監聽alertdialog中Negative Button被點擊的事件, 可以看到事件啟動之後僅把dialog dismiss,沒有作其他事情
ClickListenerForPositiveButton類別則為監聽alertdialog中Positive Button被點擊的事件, 事件啟動後檢查mSelectedItems的element,如果是true代表在dialog是被勾選的
 
2.main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/show_alert_dialog"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/show_alert_dialog" />
    <TextView
        android:id="@+id/show_selected_items"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/selected_items" />
</LinearLayout>