posts - 33, comments - 0, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          2011年8月19日

                在第一篇時就說過框架要在URL上作文章,是的,本文就框架怎樣充分利用url上作盡可能詳細的說明。

                做web開發的不可能對url陌生,早在web1.0時代,url作為統一資源定位符,在對web中資源的如何獲得上起到巨大作用。不論用戶請求的時靜態頁面或者是各種圖片、腳本文件,通過url總能從web網站獲取要訪問的資源。Web2.0更是常常使用url作為get請求時參數的傳遞,如http://xxx.xxx.xxx/xxx.jsp?user=admin。以及近幾年很火restful web service 摒棄soap而使用url傳遞請求參數 都說明合理利用url的可行和流行。

                當然不止是使用了url就算好的實踐,而是能夠做到優雅的使用,保證層次分明和整體的簡潔,這才算是好的方式,這也正是本框架對使用url 所追求的目標。

                首先來看幾個例子:

          http://www.cnblogs.com/p2
          http://www.xxx.com/index.do?page=2

          http://www.xxx.com/product/
          http://www.xxx.com/channel.do?channel=product

          http://www.xxx.com/product/mobile
          http://www.xxx.com/channel.do?channel=product&&subChannel=mobile

                相信各位看官不用我說也能明白,這幾組的實現肯定第一種實現的方式更佳。拋開它能屏蔽服務器端使用的技術這一特性不說,它還能夠更好地說明動態網站的層次結構,讓用戶在訪問時能明確知道在網站的什么位置,而不會覺得是陷入了一個迷宮。

                當然上面列舉的例子是網站前端所使用的url表現方式,因為表現方式可以多種多樣,個人喜好不同,本框架在設計時沒有給指定前端url的表現方式,而是定義接口,把這個權利留給使用的用戶。框架將考慮更多 通用性的東西而不是 個性 自由的東西。

           

                下面對框架里默認使用的url Router AMPPathRouter做詳細的介紹,包括設計的思想和實現的方式。首先AMPPathRouter的用途定位為后臺使用。為了理解快速的理解它的工作原理,先來和struts做一下對比。

                Struts關于請求的配置:

           

          <action name="login" class="com.lscmjx.action.LoginAction" method="login">
          <result name="success">
          main.jsp
          </result>
          <result name="failure">
          login.jsp
          </result>
          </action>

              它提交的url會是http://xxx.xxx.xxx/login,訪問web服務器時會把此url傳遞到struts框架交給它處理,之后struts會在struts.xml中尋找login的相關的配置,像上面例子,struts會找到LoginAction的類,并且調用其login的方法。

                寫到這里,我請問這是最好的方式嗎?當然不是,至少我在使用struts時就認為這是相當撇腳的設計。上面例子只是列舉一個login方法,假如一個系統中要對后臺調用的方法是100個,那豈不是就需要在struts.xml中寫100個與之類似的配置。想想都頭大,這樣繁瑣的工作,應該是由框架自己去處理,而不是人工給配置。

           

                再來看實現相同功能的Unicorn web框架的配置。

           

          <action class="com.mh.action.UserAction"></action>

                當然提交的url肯定需要包含多一些的信息,來保證能通過url正確調用框架Action里的方法。這里提交的url方式:http://xxx.xxx.xxx/UserAction/login/

                通過在url里附加調用的Action類的信息,可以省略為不同的方法都在xml里配置的麻煩。假如UserAction里有100個方法,框架也只需這一行的配置。

                有了大體的認識之后,來看框架的核心部分AMPPathRouter的具體實現。

           

            /**
          * 檢查url是否是此Router類要處理的,/Action/Method/Param 格式的將會被檢查合格,返回true
          *
          @param relativeUri
          *
          @param actionMap
          *
          @return
          */
          public boolean checkUrl(String relativeUri, Map<String, ActionSupport> actionMap) {
          Pattern pattern = Pattern.compile("^/\\w+/\\w+/\\S*");
          Matcher matcher = pattern.matcher(relativeUri);
          if(matcher.matches()) {
          String actionName = relativeUri.split("/")[1];
          ActionSupport actionSupport = actionMap.get(actionName);
          if(null != actionSupport) {
          String actionMethodName = relativeUri.split("/")[2];
          Class<?> actionClass = actionSupport.getClass();
          Method[] methods = actionClass.getMethods();
          for(int i = 0; i < methods.length; i++) {
          Method method = methods[i];
          String methodName = method.getName();
          if(methodName.equals(actionMethodName)) {
          return true;
          }
          }
          } else {
          return false;
          }
          }
          return false;
          }
          /**
          * 匹配規則為:
          * 1、符合/Action/method/param格式,
          * 2、并且Action在actionMap中的確存在
          * 3、method在此Action中存在
          */
          @Override
          public boolean route(String relativeUri, UrlFilter urlFilter) {
          Map<String, ActionSupport> actionMap = urlFilter.getActionMap();
          if(!this.checkUrl(relativeUri, actionMap)) {
          return false;
          }
          // 攔截Action/Method/Param方式的請求,并構建ActionSupport類的屬性
          String[] params = relativeUri.split("/");
          try {
          ActionSupport actionSupport = actionMap.get(params[1]);
          Class<?> action = actionSupport.getClass();
          Method method = action.getMethod(params[2], new Class[] {});
          if(params.length > 3) {
          this.boxingRequest(urlFilter.getRequest(), params[3]);
          }
          // 只要找到ActionSupport的子類,則初始化其所具有的屬性
          Object newInstance = action.newInstance();
          this.initActionSupport(newInstance, urlFilter);
          String result = (String) method.invoke(newInstance, new Object[] {});
          if (null == result || ActionSupport.AJAX.equals(result) || ActionSupport.FORWARD.equals(result) || ActionSupport.WEB_SERVICE.equals(result)) {
          return true;
          }
          if(ActionSupport.REDIRECT.equals(result)) {
          urlFilter.getResponse().sendRedirect(result);
          return true;
          }
          } catch (NoSuchMethodException e) {
          e.printStackTrace();
          } catch (SecurityException e) {
          e.printStackTrace();
          } catch (IllegalAccessException e) {
          e.printStackTrace();
          } catch (IllegalArgumentException e) {
          e.printStackTrace();
          } catch (InvocationTargetException e) {
          e.printStackTrace();
          } catch (InstantiationException e) {
          e.printStackTrace();
          } catch (Exception e) {
          e.printStackTrace();
          }
          return false;
          }
          /**
          * 把url中得param加入到request的attribute里
          *
          @param request
          *
          @param parameter
          */
          private void boxingRequest(HttpServletRequest request, String parameter) {
          String[] parameters = parameter.split("&");
          for (int i = 0; i < parameters.length; i++) {
          String param = parameters[i];
          String[] key_value = param.split("=");
          if(key_value.length == 2) {
          request.setAttribute(key_value[0], key_value[1]);
          }
          }
          }
          /**
          * 初始化ActionSupport類中所需的request、response、session、application等對象
          *
          @param obj
          *
          @param urlFilter
          */
          private void initActionSupport(Object obj, UrlFilter urlFilter) {
          ActionSupport action = (ActionSupport) obj;
          action.setRequest(urlFilter.getRequest());
          action.setResponse(urlFilter.getResponse());
          action.setSession(urlFilter.getSession());
          action.setApplication(urlFilter.getApplication());
          }

           

                這便是AMPPathRouter的全部內容,其中在把請求分發到ActionSupport的子類 并調用相關方法時 是通過反射實現,其他地方地方都是相當容易理解的。

                空說無憑,把框架應用到實戰中才是硬道理:

           

                好了,下一篇介紹Action 和 json。

          posted @ 2011-11-25 18:18 馬航 閱讀(270) | 評論 (0)編輯 收藏

                上篇說過,所有提交到web程序的url都被此UrlFilter攔截。攔截到請求后,UrlFilter則召集它的好多個得力干將Router 們, 詢問他們:“誰能處理此URL啊 ?”

          這時一位叫做AMPRouter 首當其沖 說:“這個url交給我了”。這時filter就會把此url全權交給AMPRouter來辦,至于如何去處理,filter也不再過問,它覺得:“我把任務都交給你了,怎么解決是你的事”。

                根據單一職責的原則,UrlFilter就負責上面情景中的分發urlRouter中的差事,url如何分發交給Router處理。并且Router實際是一個接口,使用框架的用戶完全可以自己實現Router,這樣用戶可以自主定義的url分發的策略。另外呢,框架初始化的一些操作它也是 推脫不掉的,像根據unicorn-config.xml初始化系統中的RouterAction'。下面是具體的代碼:

           

          @Override
          public void init(FilterConfig config) throws ServletException {
          	application = config.getServletContext();
          	String loadPath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
          	String classPath = loadPath.substring(1, loadPath.length());
          	ArrayList<String> actions = XMLReader.getNodeValues(classPath + "unicorn-config.xml", "actions");
          	this.initActions(actions);
          	ArrayList<String> routers = XMLReader.getNodeValues(classPath + "unicorn-config.xml", "routers");
          	this.initRouters(routers);
          }

           

          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
          			throws IOException, ServletException {
          	HttpServletRequest request = (HttpServletRequest) servletRequest;
          	String path = request.getContextPath();
          	String uri = request.getRequestURI();
          	String relativeUri = uri.substring(path.length(), uri.length());
          	this.request = request;
          	this.session = request.getSession();
          	this.response = (HttpServletResponse) servletResponse;
          	// 用戶自定義的Router優先級最高,url先通過用戶定義的
          	Iterator<IPathRouter> iterator = routerList.iterator();
          	while(iterator.hasNext()) {
          		IPathRouter router = iterator.next();
          		if(router.route(relativeUri, this)) {
          			return ;
          		}
          	}
          	// 攔截不到的繼續訪問
          	filterChain.doFilter(servletRequest, servletResponse);
          }
          

                  其中Router類的初始化,Action類的初始化于這個類似:

          private void initRouters(ArrayList<String> routers) {
          	routerList = new ArrayList<IPathRouter>();
          	for (int i = 0; i < routers.size(); i++) {
          		String routerName = routers.get(i);
          		try {
          			Class<?> clz = Class.forName(routers.get(i));
          			// 單例模式通過方法獲取對象實例
          			IPathRouter router = (IPathRouter) clz.newInstance();
          			routerList.add(router);
          		} catch (ClassNotFoundException e) {
          			e.printStackTrace();
          		} catch (IllegalAccessException e) {
          			e.printStackTrace();
          		} catch (SecurityException e) {
          			e.printStackTrace();
          		} catch (IllegalArgumentException e) {
          			e.printStackTrace();
          		} catch (InstantiationException e) {
          			e.printStackTrace();
          		}
          	}
          	// 最后把框架默認的Router加入進來
          	routerList.add(new AMPPathRouter());
          }
          

                  其中unicorn-config.xml文件的編寫,拿其中我一個項目里的這個文件來舉例:

          <?xml version="1.0" encoding="UTF-8" ?>
          <config>
          <routers>
          <router class="com.mh.router.MySessionCheckRouter"></router>
          </routers>
          <actions>
          <action class="com.mh.action.UserAction"></action>
          <action class="com.mh.action.InformationAction"></action>
          <action class="com.mh.action.UploadInformationIconAction"></action>
          <action class="com.mh.action.TempPicAction"></action>
          <action class="com.mh.action.MobileAction"></action>
          </actions>
          </config>

                這里即定義了Action,也定義了自己的Router,并且從名稱上可以看出,這個SessionCheckRouter是要判斷所有提交到服務器的指定url的請求 是否已經登錄過,沒有登錄,可能會把此請求遣送會登錄頁。以及初始化所有的Action,在Router處理完請求,分發給action時,可以從filter里面去取。

           


          posted @ 2011-11-25 12:35 馬航 閱讀(274) | 評論 (0)編輯 收藏

                承接上篇的簡單介紹,下面詳細介紹整個框架的大致結構。

                先來看一下整個框架包的結構:

           

                可以看出框架包含的包很少,包的結構也超簡單。這里 涉及FilterActionSupportRouter等三個概念,他們之間的關系,通過下圖來表示:

           

                圖也不規范,說不上來是哪個UML圖,不過通過它也能看出一個請求到達時,框架基本的處理流程。首先由Filter攔截到所有請求,然后把請求交給所有注冊的Router類,如果請求的Url正好是一個Router要攔截的,則把此請求交給這個Router,框架不再把請求向下傳遞。Router得到請求后,分析Url,通過Url里的信息把請求交給對應的ActionSupport的子類來處理。

                這里攔截采用Filter來處理,這跟多數的web框架一樣,使用FilterServlet有更多的能力進行請求的分發。首先在一個web工程的web.xml文件中配置框架的UrlFilter類來攔截所有的請求。需要注意的一點是dispatcher 要設置為request,如果設置了forward的話,由框架內部進行的forward又會被框架攔截,從而造成無限的循環。Url-pattern設置為/*,表示所有的請求都會攔截,從而把對url分發的權利交由框架本身,而不是采用jsp規范里的url分發策略。框架在處理所有請求的url 時,依次交給各個Router類來處理,如果Router類判斷是符合自己的url格式,則分發給 action 處理。如果不能處理再交給下一級的Router,最后url經由所有Router處理完,剩下的資源文件的url,如http://xxx.xxx.xxx.jpg,則框架調用filterdoChain()方法,通過filter的過濾去訪問web里的資源。

          <filter>

                <filter-name>unicornWeb</filter-name>

                <filter-class>com.mh.mvc.filter.UrlFilter</filter-class>

          </filter>

          <filter-mapping>

              <filter-name>unicornWeb</filter-name>

              <url-pattern>/*</url-pattern>

              <dispatcher>REQUEST</dispatcher>

          </filter-mapping>

                大致的原理就是這樣,在下篇介紹框架的詳細實現。

          posted @ 2011-11-25 11:43 馬航 閱讀(350) | 評論 (0)編輯 收藏

                我承認有點標題黨了,不過題目中所說的幾項技術確實有其相似之處,欲知事情原委,且聽我詳細道來。

                項目一開始只是不滿 struts 龐大的體積,于是想自己根據其原理實現一個tiny 版。后來的開發中覺得,完全可以把上述的ajax、Restuful web service的一些思想加入進來。經過幾周的努力,便開發出了一個基本成型的web 框架,暫且起名為unicorn(獨角獸,吼吼)。下文開始便對這個自編寫的框架做一些列的介紹,并且初步打算是將其開源,希望能一起交流和完善它。

                首先,為了能快速了解它是什么,先來看一下配置文件:

          <?xml version="1.0" encoding="UTF-8" ?>
          <config>
          <routers>
          <router class="com.mh.router.MySessionCheckRouter"></router>
          </routers>
          <actions>
          <action class="com.mh.action.UserAction"></action>
          <action class="com.mh.action.InformationAction"></action>
          <action class="com.mh.action.MobileAction"></action>
          </actions>
          </config>

                上面就是整個工程的配置文件,可以看出需要配置的東西非常少,只需要制定action類 和 router類有哪些就Ok。框架奉行約定大于配置的思想,至于請求如何分發,這個不需要人工配置,框架自動解決。這里要介紹兩個概念Action 和 Router,熟悉Struts的肯定都知道Action,Action替代Servlet、JSP時代的Servlet,所有提交的請求由struts分發給不同的Action來處理。這里道理也是一樣的,Action就是經過框架處理后的請求接受者。再來說一下Router,字面意思路由器,學過計算機網絡的都知道,ip數據包在網絡上之所以能夠順利到達,就是因為路由器根據路由表來來確定出來傳輸的途徑。這里Router也是這個作用,根據訪問服務器的URL來制定分發策略。Router是完全可以自定義的,用戶可以定義自己的Router來制定URL分發的策略,并且用戶自定義的Router比系統默認的Router有更高的優先權。

          二、URL上做文章

          /UserAction/login/username=admin&&password=admin

                先來介紹系統MethodRouter的處理方式。上面的url根據"/"分為三個部分,第一部分是請求的Action類,第二部分是類中的方法Method,第三部分是提交的參數Param。這一點受上篇文章優酷的架構里URL設計的啟發。

                經過這樣的設計,就明白在上述配置文件中為何可以如此簡單了。

                當然也可以不以這樣的方式,框架提供自定義Router的支持。比如你想這樣處理URL:/前臺頁面/子欄目/子欄目

                想實現上面的方式,就可以自己定義Router,在Router里面獲取上述的URL,然后做處理、forward到相應的jsp頁面。

          三、使用Json傳輸數據

                Ajax請求很容易處理json數據,ajax可以與系統輕松交互。

                當初Web Service使用SOAP的xml格式傳輸數據,如今也有人指責這是大費周折。Restful方式提倡遵循HTTP語義,完全使用URL結合GET、POST、PUT、DELETE來傳輸請求,結果在roil陣營里廣泛使用,認為是web service更優雅的方式。所以本框架也吸取他們的優點,也完全可以通過url傳輸請求的數據,如上述URL中的Param部分。不過沒有遵循Restful強調的Http語義,全部使用Get和POST的請求方式,當然也可以制定為其他,這完全看你的心情,因為這對功能實現無關緊要。而且我覺得統一使用一種,更避免了需要指定請求方式的麻煩。

                數據的返回使用json格式,比SOAP更為輕量簡潔和優雅,而且有更多的平臺直接支持。如在android平臺,本身就支持json格式的處理, 如果使用web service 的SOAP,你可能還要導入KSOAP的第三方庫。

                在非瀏覽器的客戶端,可以借助編寫的工具類,來完成web service方式的操作,

          public interface IWebService {
          	public List<LiteInformationDTO> getInformationsOfOwnerApp(String ownerApp, int start, int limit) throws SocketTimeoutException;
          }
          

                經過這樣的封裝,已經與使用web service毫無差別,而且還會更加高效,因為處理json總比處理SOAP的xml要容易。

           

                先簡單寫這么多,之后的續篇詳細介紹。

          posted @ 2011-11-22 16:22 馬航 閱讀(285) | 評論 (0)編輯 收藏

          記得以前給大家介紹過視頻網站龍頭老大YouTube的技術架構,相信大家看了都會有不少的感觸,互聯網就是這么一個神奇的東西。今天我突然想到,優酷網在國內也算是視頻網站的老大了,不知道他的架構相對于YouTube是怎么樣的,于是帶著這個好奇心去網上找了優酷網架構的各方面資料,雖然談得沒有YouTube那么詳細,但多少還是挖掘了一點,現在總結一下,希望對喜歡架構的朋友有所幫助。

          一、網站基本數據概覽

          • 據2010年統計,優酷網日均獨立訪問人數(uv)達到了8900萬,日均訪問量(pv)更是達到了17億,優酷憑借這一數據成為google榜單中國內視頻網站排名最高的廠商。
          • 硬件方面,優酷網引進的戴爾服務器主要以 PowerEdge 1950與PowerEdge 860為主,存儲陣列以戴爾MD1000為主,2007的數據表明,優酷網已有1000多臺服務器遍布在全國各大省市,現在應該更多了吧。

          二、網站前端框架

          從一開始,優酷網就自建了一套CMS來解決前端的頁面顯示,各個模塊之間分離得比較恰當,前端可擴展性很好,UI的分離,讓開發與維護變得十分簡單和靈活,下圖是優酷前端的模塊調用關系:

          這樣,就根據module、method及params來確定調用相對獨立的模塊,顯得非常簡潔。下面附一張優酷的前端局部架構圖:

           

          三、數據庫架構

          應該說優酷的數據庫架構也是經歷了許多波折,從一開始的單臺MySQL服務器(Just Running)到簡單的MySQL主從復制、SSD優化、垂直分庫、水平sharding分庫,這一系列過程只有經歷過才會有更深的體會吧,就像MySpace的架構經歷一樣,架構也是一步步慢慢成長和成熟的。

          1、簡單的MySQL主從復制:

          MySQL的主從復制解決了數據庫的讀寫分離,并很好的提升了讀的性能,其原來圖如下:

          其主從復制的過程如下圖所示:

          但是,主從復制也帶來其他一系列性能瓶頸問題:

          1. 寫入無法擴展
          2. 寫入無法緩存
          3. 復制延時
          4. 鎖表率上升
          5. 表變大,緩存率下降

          那問題產生總得解決的,這就產生下面的優化方案,一起來看看。

           

          2、MySQL垂直分區

          如果把業務切割得足夠獨立,那把不同業務的數據放到不同的數據庫服務器將是一個不錯的方案,而且萬一其中一個業務崩潰了也不會影響其他業務的正常進行,并且也起到了負載分流的作用,大大提升了數據庫的吞吐能力。經過垂直分區后的數據庫架構圖如下:

          然而,盡管業務之間已經足夠獨立了,但是有些業務之間或多或少總會有點聯系,如用戶,基本上都會和每個業務相關聯,況且這種分區方式,也不能解決單張表數據量暴漲的問題,因此為何不試試水平sharding呢?

           

          3、MySQL水平分片(Sharding)

          這是一個非常好的思路,將用戶按一定規則(按id哈希)分組,并把該組用戶的數據存儲到一個數據庫分片中,即一個sharding,這樣隨著用戶數量的增加,只要簡單地配置一臺服務器即可,原理圖如下:

          如何來確定某個用戶所在的shard呢,可以建一張用戶和shard對應的數據表,每次請求先從這張表找用戶的shard id,再從對應shard中查詢相關數據,如下圖所示:

          但是,優酷是如何解決跨shard的查詢呢,這個是個難點,據介紹優酷是盡量不跨shard查詢,實在不行通過多維分片索引、分布式搜索引擎,下策是分布式數據庫查詢(這個非常麻煩而且耗性能)

           

          四、緩存策略

          貌似大的系統都對“緩存”情有獨鐘,從http緩存到memcached內存數據緩存,但優酷表示沒有用內存緩存,理由如下:

          1. 避免內存拷貝,避免內存鎖
          2. 如接到老大哥通知要把某個視頻撤下來,如果在緩存里是比較麻煩的

          而且Squid 的 write() 用戶進程空間有消耗,Lighttpd 1.5 的 AIO(異步I/O) 讀取文件到用戶內存導致效率也比較低下。

          但為何我們訪問優酷會如此流暢,與土豆相比優酷的視頻加載速度略勝一籌?這個要歸功于優酷建立的比較完善的內容分發網絡(CDN),它通過多種方式保證分布在全國各地的用戶進行就近訪問——用戶點擊視頻請求后,優酷網將根據用戶所處地區位置,將離用戶最近、服務狀況最好的視頻服務器地址傳送給用戶,從而保證用戶可以得到快速的視頻體驗。這就是CDN帶來的優勢,就近訪問,有關CDN的更多內容,請大家Google一下。

          好了,就總結這么多了,有興趣的同學接著補充,雖然很多資料圖片都來自網絡,但整理也不容易,歡迎轉載,轉載留個出處:青藤屋 原文鏈接

          posted @ 2011-11-02 11:23 馬航 閱讀(289) | 評論 (0)編輯 收藏

          windows系統使我們經常使用的操作系統怎么才能使用我們現在經常使用的操作系統不變的情況下繼續我們的SVN之旅,我們在綜合了好動種方法的同時感覺這些內容非常貼近我們SVN在Windows種的應用與配置.

          1.下載文件,

          下載最新版本subversion,我這里選擇svn-1.4.5-setup.exe

          下載 "Subversion Windows Service" 軟件包

          下載 TortoiseSVN shell integration utility

          2.安裝Subversion 服務器

          由于我下載的是setup.exe版本,安裝程序安裝后會自動設置系統變量.如果你下載的是zip版就需要手動設置系統變量.

          setup.exe版直接安裝就可以了.安裝到D:/Program Files/Subversion

          首先創建SVN儲存庫(repository)

          svnadmin create F:/svn/

          repository創建完畢后會在目錄下生成若干個文件和文件夾,dav目錄是提供給Apache與mod_dav_svn使用的目錄,讓它們存儲內部數據;db目錄就是所有版本控制的數據文件;hooks目錄放置hook腳本文件的目錄;locks用來放置Subversion文件庫鎖定數據的目錄,用來追蹤存取文件庫的客戶端;format文件是一個文本文件,里面只放了一個整數,表示當前文件庫配置的版本號;

          3.配置SVN服務器

          (這個位置就是在你建儲存庫的地方F:/svn)

          打開/conf/目錄,打開svnserve.conf找到一下兩句:

          # [general]

          # password-db = passwd

          # anon-access = none

          # auth-access = write

          去之每行開頭的#,其中第二行是指定身份驗證的文件名,即passwd文件.anon-access = none 是匿名用戶不能訪問,必須要有用戶名和密碼。(注意:問題就出在這,一定要注意格式去掉注釋后要頂格不能有空)

          同樣打開passwd文件,將

          # [users]

          # harry = harryssecret

          # sally = sallyssecret

                 格式為“用戶名 = 密碼”,如可插入一行:admin = admin888,即為系統添加一個用戶名為admin,密碼為admin888的用戶

          4.運行SVN服務器

          運行SVN服務

          在命令行執行

          svnserve --daemon --root F:/svn

          服務啟動,--daemon可簡寫為-d,--root可簡寫為-r,可以建立一個批處理文件并放在windows啟動組中便于開機就運行SVN服務(注意:這是臨時打開的服務,命令執行后不能關閉窗口)

          也可以制定subversion工作的端口:svnserve -d -r f:/svn --listen-port 9999

          用后臺服務的方式可以設置開機自動執行。

          D:/Program Files/Subversion/bin>sc create svnservice binpath= "C:/Program Files/Subversion/bin/svnserve.exe --service -r f:/svn  --listen-port 9999"

          就可以用net svnservice stop 或者start來啟動服務了 也可以在Sevices.msc來啟動了。

          5、用客戶端訪問

          格式:svn://服務器IP

           

          ---------------------------------------------------------------------------------------------------------

           

          基于svnserve的服務器,權限文件authz配置的常見問題及解答  
           最近在我用Subversion論壇(http://www.iUseSVN.com/bbs)經常有人提到這樣的問題: 
          為什么我的客戶端沒有寫權限? 
          為什么我的權限沒有起作用?

          總結他們的配置,發現 
          都是用svnserve作為服務器, 
          都在svnserve.conf中使用了authz-db選項

          原因可能如下:

          1,配置authz時,沒有注意svnserve啟動參數-r所指定的目錄。 
          這里有兩種情況: 
          A:-r直接指定到版本庫(稱之為單庫svnserve方式) 
          比如,有一個庫project1,位于D:/svn/project1 
          使用以下命令啟動svnserve

          [Copy to clipboard] [ - ]CODE: 
          svnserve -d -r D:/svn/project1 
          在這種情況下,一個svnserve只能為一個版本庫工作 
          authz文件如果配置成下面這樣就是錯的,

          [Copy to clipboard] [ - ]CODE: 
          [groups] 
          admin=user1 
          dev=user2 
          [project1:/] 
          @admin=rw 
          @doc=r 
          應該配置成

          [Copy to clipboard] [ - ]CODE: 
          [groups] 
          admin=user1 
          dev=user2 
          [/] 
          @admin=rw 
          @doc=r 
          因為[project1:/]表示庫project1的根目錄,而按上面的啟動參數,是沒有庫的概念的。 
          使用類似這樣的URL:svn://192.168.0.1/ 即可訪問project1

          B:-r指定到版本庫的上級目錄(稱之為多庫svnserve方式) 
          同樣,有一個庫project1,位于D:/svn/project1 
          如果使用以下命令啟動svnserve

          [Copy to clipboard] [ - ]CODE: 
          svnserve -d -r D:/svn 
          這種情況,一個svnserve可以為多個版本庫工作, 
          這時如果想限制指定庫的指定目錄,就應該指定具體的庫,像這樣

          [Copy to clipboard] [ - ]CODE: 
          [groups] 
          admin=user1 
          dev=user2 
          [project1:/] 
          @admin=rw 
          @doc=r 
          如果此時你還用[/],則表示所有庫的根目錄,同理,[/src]表示所有庫的根目錄下的src目錄 
          使用類似這樣的URL:svn://192.168.0.1/project1 即可訪問project1 
          這樣的URL:svn://192.168.0.1/project2 即可訪問project2

          2,對中文目錄進行權限控制時,沒有將權限文件authz改為utf-8格式。

          svn對于非英文文件名和目錄名使用utf-8格式編碼處理,要對中文目錄進行正確控制, 
          應該使用無BOM的utf-8格式,如何將默認的文件轉為utf-8, 
          我使用的是UltraEdit的菜單"ASCII to UTF-8 (Unicode Editing)"。在UltraEdit的配置中,可以設置有無BOM  

          posted @ 2011-10-12 17:26 馬航 閱讀(424) | 評論 (0)編輯 收藏

          SIP協議

           

          SIP協議過程概念及分析

           

          SIP入門開發之路(含SIP開發需要學習的資源及網址)

           

          SIP揭密(中文版)

           

          使用Java的SIP Servlet進行SIP開發

           

           

          Asterisk:

           

          Asterisk安裝及測試

           

          Asterisk十問十答

           

          Asterisk入門教程

           

          Asterisk介紹-Asterisk RealTime SIP

          asterisk配置文件列表及常用指令

           

          asterisk 官方文檔

           

          asterisk目錄及配置說明

           

          Asterisk功能整理

           

          Asterisk使用ODBC實現語音信箱

           

          使用Asterisk實現可視的語音交換

           

           

          OpenSIPS

           

          開源SIP服務器OpenSIPS應用介紹

           

          Opensips 安裝

           

          Opensips 配置文件

           

          Mediaproxy的安裝及其在OpenSIPS中的配置

           

          Opensips文檔之MediaProxy模塊

           

          使用OpenSIPS構建電話通信系統-8媒體服務整合

           

          使用OpenSIPS構建電話通信系統-4腳本及路由基礎

           

          Opensips文檔之TM模塊

           

          Opensips文檔之RR模塊

           

          Opensips文檔之TEXTOPS 模塊

           

          Opensips文檔之AVPOPS模塊

           

           

          NAT穿透(即SIP打洞)

           

          使用OpenSIPS構建電話通信系統-SIP穿透NAT

           

          NAT穿透問題探討

           

          完美的NAT穿透技術ICE介紹

           

          ICE-SIP穿透NAT問題的終極解決方案

           

          NAT穿透技術ICE基礎教程

          posted @ 2011-10-07 20:31 馬航 閱讀(455) | 評論 (0)編輯 收藏

               摘要: Android中有一控件是ExpandableListView,比ListView更高級,ExpandableListView的效果很實用,比如因為需要查看一堆文件的目錄結構或者開發像QQ好友那樣的界面,就應該使用Expandablelistview。 本文最終效果如下: 首先是Activity代碼,實際開發中數據(包括父item,子item及圖片,Expandablelistview...  閱讀全文

          posted @ 2011-10-06 09:37 馬航 閱讀(5471) | 評論 (0)編輯 收藏

          前言:做完了手機全能播放器的項目, 又要告別幾個月來并肩作戰,即將去北京發展的Manager zhu。準備把做過的3GP/FLV/AVI格式整理一遍, 算是對幾個月辛苦成果的總結, 也為后來者提供一些參考。

          1. 概述

          流行的文件格式背后都有大公司的支持。FLV得益于ADOBE公司推動的網絡視頻分享風潮,而AVI則是MICROSOFT首創的RIFF即視頻和音頻交織在一起同步播放。 3GP/MP4是APPLE提出并得到ISO標準支持作為NOKIA等手機的默認視頻格式。3GP是MP4格式在手機上的簡化版。MP4的codec組合一般是mpeg4 + AAC, 3GP則按版本演進分為3gpp r5(h.263/mpeg4 + AMR-NB/AMR WB), 3gpp r6(增加h.264視頻和aacPlus音頻支持)。

          有人會把MP4和MPEG4搞混, 前者是文件容器(container),后者是視頻編碼格式, 容器的作用是把壓縮編碼后的視頻和音頻數據盡可能緊湊的排布,就好像阿甘的巧克力盒子,你并不知道盒子里有什么, 但你可以按照既定的線索解開文件,取出你需要的數據。

          文件格式一般包括以下三要素:

          header: 標記文件類型,音視頻碼流的基本屬性信息
          index: 索引表,每個frame有對應的offset,size,timestamp.
          stream: 真正的音視頻流數據。
          任何文件格式都應該有以上3要素。 當然AVI視頻沒有索引也能播放,但不能拖放seek,需要自己重建索引。解析器(demuxer)根據frame_id找到其在文件中的offset和size,然后讀取出來解碼并播放。

          2. 文件格式分析

          下面來分析一下3GP/MP4文件格式。APPLE的格式有2個特點,1. 排布緊湊幾乎沒有冗余數據(AVI則有很多junk數據),2.音視頻碼流數據可隨意存放而不需按時間順序排布。

          3gp文件由一系列的box(atom)組成。每個box的結構都是4字節的size,4字節的type, 還有一些data數據。用mp4info查看3gp文件的數據排布如下圖:

          如上圖, ftyp是表示文件的版本信息, mdat存放文字,音視頻等數據。你可能要問,這些音視頻數據怎么找到呢? 是通過moov box里的子box trak,里面存放著音視頻的屬性描述以及每個sample的索引。

          3. 關于sample atoms

             video和audio的碼流屬性(如視頻width/height,codec id, 音頻采樣率聲道數等)存放在stsd box里; 下面著重介紹MP4高效壓縮的精華:stts,stss,stsc,stsz,stco五個box。對比AVI的索引表是每個sample都有對應的id,flag,offset,size,3GP的高效索引方式可以把AVI轉碼成同碼率的MP4后,文件size減小成原來的20-30%!

          1. stts atom(time to sample atoms,見quicktime format 文檔圖2-28 標準文檔點擊下載): 存儲了sample的時間信息。stts能讓很方便的根據timestamp找到對應的sample,或者獲取某個sample對應的timestamp. sttstable記錄著有相同duration的sample的數量count和時長dutation。

          2. stss atom(sync sample atom,見文檔圖2-31): 存儲了每個關鍵幀的sample id。 stss能讓你很方便的找到當前幀最近的關鍵幀。

          3. stsc atom(sample to chunk atom): sample存放在chunk里為了允許優化的數據讀取。比如音頻sample size都很小(amr-nb sample size為32字節), 每次讀取一個sample開銷太大, 可一次性讀所在chunk里一堆sample。

          4. stsz atom(sample size atom): stsz可以描述每個sample的size.

          5. stco atom(chunk offset atoms): stco描述了每個chunk在文件中的絕對偏移位置。該offset可以是32位的

          也可以是64位的,后者用來支持處理超大文件。

          4 .使用sample atoms來處理播放流程

          · 查找sample         

          1.確定時間,相對于媒體時間坐標系統

          2.檢查time-to-sample atom來確定給定時間的sample序號。

          3.檢查sample-to-chunk atom來發現對應該sample的chunk。

          4.從chunk offset atom中提取該trunk的偏移量。

          5.利用sample size atom找到sample在trunk內的偏移量和sample的大小。

          例如,如果要找第1秒的視頻數據,過程如下:

          1. 第1秒的視頻數據相對于此電影的時間為600

          2. 檢查time-to-sample atom,得出每個sample的duration是40,從而得出需要尋找第600/40 = 15 + 1 = 16個sample

          3. 檢查sample-to-chunk atom,得到該sample屬于第5個chunk的第一個sample,該chunk共有4個sample

          4. 檢查chunk offset atom找到第5個trunk的偏移量是20472

          5. 由于第16個sample是第5個trunk的第一個sample,所以不用檢查sample size atom,trunk的偏移量即是該sample的偏移量20472。如果是這個trunk的第二個sample,則從sample size atom中找到該trunk的前一個sample的大小,然后加上偏移量即可得到實際位置。

          6. 得到位置后,即可取出相應數據進行解碼,播放

          ·       查找關鍵幀      

          查找過程與查找sample的過程非常類似,只是需要利用sync sample atom來確定key frame的sample序號

          確定給定時間的sample序號 
          檢查sync sample atom來發現這個sample序號之后的key frame 
          檢查sample-to-chunk atom來發現對應該sample的chunk 
          從chunk offset atom中提取該trunk的偏移量 
          利用sample size atom找到sample在trunk內的偏移量和sample的大小


          5 .3GP/MP4相關資源

               quicktime file format specification: 最權威的格式文檔 點擊下載
               開源的3GP/MP4解析器: ffmpeg, GPAC, helix, google opencore等 

          posted @ 2011-10-03 10:54 馬航 閱讀(696) | 評論 (0)編輯 收藏

          Android開發又將帶來新一輪熱潮,很多開發者都投入到這個浪潮中去了,創造了許許多多相當優秀的應用。其中也有許許多多的開發者提供了應用開 源項目,貢獻出他們的智慧和創造力。學習開源代碼是掌握技術的一個最佳方式。下面推薦幾個應用開源項目,這些項目不僅提供了優秀的創意,也可以直接掌握 Android內核的接口使用:

          1、Android團隊提供的示例項目

          如果不是從學習Android SDK中提供的那些樣例代碼開始,可能沒有更好的方法來掌握在Android這個框架上開發。由Android的核心開發團隊提供了15個優秀的示例項目,包含了游戲、圖像處理、時間顯示、開始菜單快捷方式等。
          地址:http://code.google.com/p/apps-for-android/

          2、 Remote Droid

          RemoteDroid是一個Android應用,能夠讓用戶使用自己的無線網絡使用無線鍵盤、觸摸屏操作手機。這個項目為開發者提供了如網絡連接、觸摸屏手指運動等很好的樣例。
          地址:http://code.google.com/p/remotedroid/

          3、 TorProxy和Shadow

          TorProxy應用實現了Android手機無線電電傳通訊(TOR),和Shadow應用一起使用,可以使用手機匿名上網。從該項目源代碼中,可以掌握socket連接、管理cookie等方法。
          地址:http://www.cl.cam.ac.uk/research/dtg/code/svn/android-tor/

          4、 Android SMSPopup

          SMSPopup可以截獲短信內容顯示在一個泡泡形狀的窗口中。從這個項目中可以掌握到如何使用內置的短信SMS接口。
          地址:http://code.google.com/p/android-smspopup/

          5、 Standup Timer

          Standup Timer應用用于控制站立會議時間,類似秒表倒計時,可以提醒每個人的講話時間已到,從而保證每個與會者使用時間一樣。從該項目的代碼中,可以學會如何使用時間函數。另外,這個項目的代碼是采用視圖view、模型model嚴格分離的設計思路。
          地址:http://github.com/jwood/standup-timer

          6、 Foursquare

          是Foursquare.com的一個客戶端應用,該應用主要分為兩個模塊:API(com.joelapenna.foursquare)和界面前端 (com.joelapenna.foursquared)兩部分。從該項目代碼中,可以學會如何同步、多線程、HTTP連接等技術。
          地址:http://code.google.com/p/foursquared/

          7、 Pedometer

          Pedometer應用用于記錄你每天走路步數的。盡管記錄不一定精準,但是從這個項目中,可以學習幾個不同的技術:加速器交互、語音更新、后臺運行服務等。
          地址:http://code.google.com/p/pedometer/

          8、 OpenSudoku-android

          OpenSudoku是一個簡單的九宮格數獨游戲。從代碼中可以學習到如何在視圖中顯示表格數據,以及如何和一個網站交互等技術。
          地址:http://code.google.com/p/opensudoku-android/

          9、 ConnectBot

          ConnectBot是Android平臺的一個客戶端安全殼應用。從該項目代碼中,可以學習到很多Android安全方面的內容,這些是你在開發應用時經常需要考慮的安全問題。
          地址:http://code.google.com/p/connectbot/

          10、 WordPress的Android應用

          當然在最后不能不提WordPress的Android應用了,這是WordPress官方開發團隊提供的一個項目。從代碼中可以學習到XMLRPC調用(當然還有更多的優秀內容)。
          地址:http://android.svn.wordpress.org/trunk/

          posted @ 2011-10-03 09:47 馬航 閱讀(482) | 評論 (0)編輯 收藏

          導讀:對于Android開發者來說,成系列的技術文章對他們的技術成長幫助最大。如下是我們向您強烈推薦的主題為Android開發的第一個系列文章。

          文章皆來自CSDN網友maxleng的專欄,maxleng是名Android愛好者,長期從事嵌入式系統及手機軟件系統研究,自2010年4月起,在CSDN上先后發表28篇《Android核心分析》系列博文,收到網友們的極高評價。《Android核心分析》整理如下:

          1. 方法論探討之設計意圖

          2. 方法論探討之概念空間篇

          3. 手機之硬件形態

          4. 手機的軟件形態

          5. Android基本空間劃分

          6. IPC框架分析(Binder,Service,Service manager)

          7. Service詳解

          8. Android啟動過程詳解

          9. Zygote Service詳解

          10.Android GWES基本原理篇

          11.Android GWES消息系統篇

          12.Android核心分析之Android GEWS窗口管理基本架構篇

          13.Android GWES窗口管理詳解

          14.Android GWES輸入系統篇

          15.Android GWES輸入系統之輸入路徑詳解

          16.Android電話系統-概述篇

          17.Android電話系統之Rild服務詳解

          18.Android電話系統之GSMCallTracker

          19.Android電話系統之RIL-Java

          20.Android應用程序框架之無邊界設計意圖

          21.Android應用框架之AndroidApplication

          22.Android應用框架之Activity

          22.Andoird GDI之基本原理及其總體框架

          23.Android GDI之顯示緩沖管理

          24.Android GDI之共享緩沖區機制

          25.Android GDI之共享緩沖區機制

          26.Android GDI之SurfaceFlinger

          27.Android GDI之SurfaceFlinger之動態結構示意圖

          28.Android GDI之Surface&Canvas

          原文地址:http://mobile.csdn.net/a/20110209/291511.html

          posted @ 2011-09-23 15:34 馬航 閱讀(110) | 評論 (0)編輯 收藏

          新手學堂:嵌入式Linux操作系統學習規劃
          ARM+LINUX路線,主攻嵌入式Linux操作系統及其上應用軟件開發目標:
          (1) 掌握主流嵌入式微處理器的結構與原理(初步定為arm9)
          (2) 必須掌握一個嵌入式操作系統 (初步定為uclinux或linux,版本待定)
          (3) 必須熟悉嵌入式軟件開發流程并至少做一個嵌入式軟件項目。
          從事嵌入式軟件開發的好處是:
          (1)目前國內外這方面的人都很稀缺。這一領域入門門檻較高,所以非專業IT人員很難切入這一領域;另一方面,是因為這一領域較新,目前發展太快,大多數人無條件接觸。
          (2)與企業計算等應用軟件不同,嵌入式領域人才的工作強度通常低一些(但收入不低)。
          (3)哪天若想創業,搞自已的產品,嵌入式不像應用軟件那樣容易被盜版。硬件設計一般都是請其它公司給訂做(這叫“貼牌”:OEM),都是通用的硬件,我們只管設計軟件就變成自己的產品了。
          (4)興趣所在,這是最主要的。
          從事嵌入式軟件開發的缺點是:
          (1)入門起點較高,所用到的技術往往都有一定難度,若軟硬件基礎不好,特別是操作系統級軟件功底不深,則可能不適于此行。
          (2)這方面的企業數量要遠少于企業計算類企業。
          (3)有少數公司經常要碩士以上的人搞嵌入式,主要是基于嵌入式的難度。但大多數公司也并無此要求,只要有經驗即可。
          (4)平臺依托強,換平臺比較辛苦。
          興趣的由來:
          1、成功觀念不同,不虛度此生,就是我的成功。
          2、喜歡思考,挑戰邏輯思維。
          3、喜歡C
          C是一種能發揮思維極限的語言。關于C的精神的一些方面可以被概述成短句如下:
          相信程序員。
          不要阻止程序員做那些需要去做的。
          保持語言短小精干。
          一種方法做一個操作。
          使得它運行的夠快,盡管它并不能保證將是可移植的。
          4、喜歡底層開發,討厭vb類開發工具(并不是說vb不好)。
          5、發展前景好,適合創業,不想自己要死了的時候還是一個工程師。
          方法步驟:
          1、基礎知識:
          目的:能看懂硬件工作原理,但重點在嵌入式軟件,特別是操作系統級軟件,那將是我的優勢。
          科目:數字電路、計算機組成原理、嵌入式微處理器結構。
          匯編語言、C/C++、編譯原理、離散數學。
          數據結構和算法、操作系統、軟件工程、網絡、數據庫。
          方法:雖科目眾多,但都是較簡單的基礎,且大部分已掌握。不一定全學,可根據需要選修。
          主攻書籍:the c++ programming language(一直沒時間讀)、數據結構-C2。

          2、學習linux:
          目的:深入掌握linux系統。
          方法:使用linux—〉linxu系統編程開發—〉驅動開發和分析linux內核。先看深,那主講原理。看幾遍后,看情景分析,對照深看,兩本交叉,深是綱,情是目。剖析則是0.11版,適合學習。最后深入代碼。
          主攻書籍:linux內核完全剖析、unix環境高級編程、深入理解linux內核、情景分析和源代。
          3、學習嵌入式linux:
          目的:掌握嵌入式處理器其及系統。
          方法:(1)嵌入式微處理器結構與應用:直接arm原理及匯編即可,不要重復x86。
          (2)嵌入式操作系統類:ucOS/II簡單,開源,可供入門。而后深入研究uClinux。
          (3)必須有塊開發板(arm9以上),有條件可參加培訓(進步快,能認識些朋友)。
          主攻書籍:毛德操的《嵌入式系統》及其他arm9手冊與arm匯編指令等。

          4、深入學習:
          A、數字圖像壓縮技術:主要是應掌握MPEG、mp3等編解碼算法和技術。
          B、通信協議及編程技術:TCP/IP協議、802.11,Bluetooth,GPRS、GSM、CDMA等。
          C、網絡與信息安全技術:如加密技術,數字證書CA等。
          D、DSP技術:Digital Signal Process,DSP處理器通過硬件實現數字信號處理算法。
          說明:太多細節未說明,可根據實際情況調整。重點在于1、3,不必完全按照順序作。對于學習c++,理由是c++不只是一種語言,一種工具,她還是一種藝 術,一種文化,一種哲學理念、但不是拿來炫耀得東西。對于linux內核,學習編程,讀一些優秀代碼也是有必要的。
          注意: 要學會舉一反多,有強大的基礎,很多東西簡單看看就能會。想成為合格的程序員,前提是必須熟練至少一種編程語言,并具有良好的邏輯思維。一定要理論結合實踐。
          不要一味鉆研技術,雖然擠出時間是很難做到的,但還是要留點余地去完善其他的愛好,比如宇宙,素描、機械、管理,心理學、游戲、科幻電影。還有一些不愿意做但必須要做的!
          技術是通過編程編程在編程編出來的。永遠不要夢想一步登天,不要做浮躁的人,不要覺得路途漫上。而是要編程編程在編程,完了在編程,在編程!等機會來了在創業(不要相信有奇跡發生,盲目創業很難成功,即便成功了發展空間也不一定很大)。
          嵌入式書籍推薦

          Linux基礎
          1、《Linux與Unix Shell 編程指南》
          C語言基礎
          1、《C Primer Plus,5th Edition》【美】Stephen Prata著
          2、《The C Programming Language, 2nd Edition》【美】Brian W. Kernighan David M. Rithie(K & R)著
          3、《Advanced Programming in the UNIX Environment,2nd Edition》(APUE)
          4、《嵌入式Linux應用程序開發詳解》
          Linux內核
          1、《深入理解Linux內核》(第三版)
          2、《Linux內核源代碼情景分析》毛德操 胡希明著
          研發方向
          1、《UNIX Network Programming》(UNP)
          2、《TCP/IP詳解》
          3、《Linux內核編程》
          4、《Linux設備驅動開發》(LDD)

          5、《Linux高級程序設計》 楊宗德著
          硬件基礎
          1、《ARM體系結構與編程》杜春雷著
          2、S3C2410 Datasheet
          英語基礎
          1、《計算機與通信專業英語》
          系統教程
          1、《嵌入式系統――體系結構、編程與設計》
          2、《嵌入式系統――采用公開源代碼和StrongARM/Xscale處理器》毛德操 胡希明著
          3、《Building Embedded Linux Systems》

          4、《嵌入式ARM系統原理與實例開發》 楊宗德著
          理論基礎
          1、《算法導論》
          2、《數據結構(C語言版)》
          3、《計算機組織與體系結構?性能分析》
          4、《深入理解計算機系統》【美】Randal E. Bryant David O’Hallaron著
          5、《操作系統:精髓與設計原理》
          6、《編譯原理》
          7、《數據通信與計算機網絡》
          8、《數據壓縮原理與應用》

          C語言書籍推薦

          1. The C programming language 《C程序設計語言》
          2. Pointers on C 《C和指針》
          3. C traps and pitfalls 《C陷阱與缺陷》
          4. Expert C Lanuage 《專家C編程》
          5. Writing Clean Code —–Microsoft Techiniques for Developing Bug-free C Programs
          《編程精粹–Microsoft 編寫優質無錯C程序秘訣》
          6. Programming Embedded Systems in C and C++ 《嵌入式系統編程》
          7.《C語言嵌入式系統編程修煉》
          8.《高質量C++/C編程指南》林銳

          盡可能多的編碼,要學好C,不能只注重C本身。算法,架構方式等都很重要。

          posted @ 2011-09-22 14:25 馬航 閱讀(107) | 評論 (0)編輯 收藏

          網上搜了N多解決方法,但是很多將log級別的,用法的,更多的是如何在logcat中設置filter進行log的過濾與查看,但是我遇到的問題是,模擬器怎么著都OK,但真機、手機進行開發調試的時候卻看不到log信息,這是很惱人的事情(畢竟模擬器跑起來太慢了)。

          剛開始沒有查到好的方法,就用try catch把exception打到一個alertdialog中,但是這樣只能看個大概,繞這個圈子沒用,最后還是在eoe的論壇上看到了解決辦法,恐怕原因是rom本身沒有打開log的開關

          問題表現:連接手機與電腦后,驅動安裝正確,USB調試模式打開,在DDMS中可以看到device及其進程的信息,但是logcat中就是沒有信息輸出
          問題原因:一些rom默認關閉logcat
          問題說明:ddms中設備名字顯示為問號不影響,即adb get-serialno顯示為問號不影響.
          解決方法:
          1.需要root權限(部分rom不需要)
          2.打開logcat,并設置level,執行命令如下(android 升級之后 adb 在 platform-tools中,不在tools中)
          adb shell
          echo 1 > /sys/kernel/logger/log_main/enable
          說明:將1寫入日志開關文件,1為開,0為關
          echo 2 >/sys/kernel/logger/log_main/priority
          說明:將代表level的2寫入優先級文件
          3.重啟adb,如果使用eclipse,先關閉eclipse,再重啟adb,再啟動eclipse
          adb kill-server
          adb start-server
          4.此時logcat應該可以工作了,如果仍舊不工作,則更新adb
          android update adb
          5.重復第三步,此時logcat應該可以工作了,如果仍舊不工作,找到個人主目錄下的android目錄,如C:\Documents and Settings\Administrator\.android
          找到這個目錄下的adb_usb.ini文件,其內容默認只有三行,全為注釋,在后面添加一行,內容為0x12d1
          6.重復第三步,此時logcat應該可以工作了

          轉自:http://www.gobbin.cn/2011/02/16/android-phone-logcat/

          posted @ 2011-09-06 16:10 馬航 閱讀(11242) | 評論 (0)編輯 收藏

          1.          app2sd是什么
          app2sd
          就是把應用程序放在SD卡上。有些android手機的用戶數據分區(userdata)比較小(比如G1只有76M),dalvikcache和用戶數據就占了大半,使得安裝了幾個軟件后就沒有空間了。為了安裝更多軟件,在SD卡上劃出部分空間用于存在新軟件和數據,使我們的手機可以使用更多軟件。

          2.          原理
          一般情況下都SD卡都默認分成一個windows可識別的分區(FAT)。因為有linux系統的權限問題,為了讓它可以存放軟件,需要把SD卡的一部分劃分成Linux的使用的ext2文件系統,然后在開機時把此分區掛載到某處,并通過鏈接的方法,讓系統從SD卡中讀取軟件

          3.          實現

          1)         SD卡分區

          a)          使用Linux系統中的工具fdisk,它是命令行工具,很快很簡單

          b)         Windows下的圖形化工具
          具體步驟見http://www.3haoweb.cn/a/digital/mobile/2010/0609/2273.html

          2)         修改boot.img使得新分區在啟動時被自動掛載

          a)          說明:

                                                 i.              也可以從網上下載帶app2sd功能的update.zip包,升級整個系統,但是那樣的話還要備份設置、數據、軟件太麻煩,所以我選擇修改我手機中自帶的boot.img,以最小的修改來實現功能

                                                ii.              修改boot.img中的initrc(系統啟動時運行的腳本,自動掛載SD卡的ext2分區)

          b)         boot.img是什么
          boot.img
          包括了2K的文件頭,后面緊跟著是用gzip壓縮過的內核,再后面是一個ramdisk內存盤(系統基本目錄結構的鏡像檔),然后緊跟著第二階段的載入器程序(這個載入器程序是可選的,在某些映像中或許沒有這部分)

          c)          修改本機的boot.img

                                                 i.              使用nandroid備份數據
          任何對系統的修改都要先備份系統數據

                                                ii.              從機器中取出當前的boot.img
          $ export PATH=$PATH:$ANDROID_DIR/out/host/linux-x86/bin/
          $ adb shell
          # cat /proc/mtd/
          查看boot對應的mtdx,一般是mtd2
          # cat /dev/mtd/mtd2 > /sdcard/boot.img
          假設boot對應mtd2
          # mkdir /system/sd1
          建立目錄以掛載分區
          # exit
          $ adb pull /sdcard/boot.img ./                 
          復制到PC

                                              iii.              解包
          下載工具split_boot.img.pl
          http://cid-f8aecd2a067a6b17.office.live.com/self.aspx/.Public/android/reference/split^_bootimg.zip
          $ ./split_boot.img.pl boot.img                  
          解包,解出內核和ramdisk包兩部分
          $ mkdir ramdisk; cd ramdisk
          $ gzip -dc ../boot.img-ramdisk.gz |cpio -i

                                              iv.              修改啟動腳本
          $ vi init.rc 
          如果是亂碼,請使用reset命令恢復一下
          mount 最后加入
          mount ext2 /dev/block/mmcblk0p2 /system/sd1 rw

                                                v.              重新打包
          $ cd ../
          $ mkbootfs ramdisk |gzip > ramdisk-new.gz
          $ mkbooting --cmdline ‘no_console_suspend=1 console=null’ --kernel boot.img-kernel --ramdisk ramdisk-new.gz -o boot_new.img
          (mkbootfs
          mkbootimg可以android源碼包中取得,和adb在一個目錄)

                                              vi.              燒寫新包到手機
          $ adb push boot_new.img /sdcard
          $ adb shell
          # cat /dev/zero > /dev/mtd/mtd2 (
          可能找錯沒空間,沒關系)
          # flash_image boot /sdcard/boot_new.im

                                             vii.              驗證是否成功
          然后重啟手機即可,重啟后用以下命令看一下是否分區是否被掛載
          $ adb shell
          $ df 
          如果看到/system/sd1項就成功了

          3)         做鏈接,使系統從SD卡讀取軟件
          建立只對軟件安裝目錄做修改(/data/app),這樣撥出SD后除了后來安裝的軟件不能使用之外,不影響手機基本功能的使用
          $ adb shell
          # mkdir /system/sd1/data/
          # cd /system/sd1/data/

          # busybox cp -a /data/app ./  
          建議做
          # busybox cp -a /data/app-private ./        
          不建議做
          # busybox cp -a /data/dalvik-cache ./
          不建議做
          # busybox cp -a /data/data ./ 
          不建議做
          # rm -r /data/app
          # ln -s /system/sd1/data/app /data/app

          ……
          其它目錄以此類推
          然后重啟手機即可

          4)         注意
          由于launcher數據庫的關系,可能桌面上看不到原來的那些應用了,不過主菜單里是有的,再建一遍快捷方式即可

          4.          參考
          http://kb.cnblogs.com/a/1743704/

          posted @ 2011-09-04 11:15 馬航 閱讀(1028) | 評論 (0)編輯 收藏

            一、 說明

          1.        下載編譯最基本的android源碼,只能在模擬器上使用,無法在真機上使用(不能生成boot.img)。這是因為沒有編譯相關機型的內核和硬件驅動。以下介紹的是用android源碼編譯出對應HTC G1的版本,和燒寫的過程。編譯生成的版本除相機以外,其它功能均正常,穩定性不錯,也很順暢。

          2.        以下步驟都經過驗證(只驗證G1手機),實驗系統ubuntu8.04,實驗日期2010712

          3.        關鍵字: android 2.2 froyo g1 源碼編譯

          二、 編譯

          1.        建立android源碼編譯目錄
          $ export ANDROID=/exports/android/android_2.2/
          $ mkdir -p $ANDROID
          $ cd $ANDROID

          2.        源碼下載
          $ repo init -u git://android.git.kernel.org/platform/manifest.git -b android-2.2_r1
          $ vi .repo/local_manifest.xml  #
          新建下載配置文件,用以下載內核,編輯內容如下

          注意:其中msm是高通芯片組,path指明下載到源碼目錄中的位置,name指明git上的項目名
          $ repo sync           # 開始下載代碼,此時需要等待較長時間

          3.        編譯內核及無線網絡驅動
          $ cd $ANDROID/kernel
          $ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- msm_defconfig          #
          設定默認的msm配置

          $ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- #
          編譯內核
          $ cd $ANDROID/system/wlan/ti/sta_dk_4_0_4_32
          $ make ARCH=arm CROSS_COMPILE=$ANDROID/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- KERNEL_DIR=$ANDROID/kerne l       
          #編譯無線網絡驅動
          cp $ANDROID/kernel/arch/arm/boot/zImage $ANDROID/device/htc/dream/kernel
          cp $ANDROID/system/wlan/ti/sta_dk_4_0_4_32/wlan.ko $ANDROID/device/htc/dream/wlan.ko

          4.        配置編譯選項
          vi device/htc/dream/AndroidBoard.mk     #若kernel存在,則不重新編譯kernel
          ifeq ($(TARGET_PREBUILT_KERNEL),)        
          TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel
          endif

          file := $(INSTALLED_KERNEL_TARGET)
          ALL_PREBUILT += $(file)
          $(file): $(TARGET_PREBUILT_KERNEL) | $(ACP)
                  $(transform-prebuilt-to-target)

          5.        編譯android源碼
          $ cd $ANDROID
          $ vi buildspec.mk #
          加入如下內容,以支持中文

          CUSTOM_LOCALES:=zh_CN
          $ source build/envsetup.sh
          $ lunch full_dream-userdebug        
          #指定編譯機型
          $ make -j2

          6.        以打補丁的方式加入不提供源碼的庫
          此時的系統可以被燒寫,但電話音樂等基本功能均不正常,需要從系統或其它升級包中提取出源碼中不包含的庫,以支持相應功能。
          HTC網站http://developer.htc.com/adp.html
          下載名為signed-dream_devphone_userdebug-ota-14721.zip的包(一個普通的update包),并把它放在$ANDROID目錄下,并將其改名為dreaem_update.zip
          $ mv signed-dream_devphone_userdebug-ota-14721.zip dream_update.zip
          $ cd device/htc/dream
          $ ./unzip-files.sh  
          此時會提示有幾個庫找不后,后面有對應解決辦法

          $ cd $ANDROID
          $ vi vendor/htc/dream/device_dream-vendor-blobs.mk
          刪除包含以下內容的行,這是由于在update.zip中找不到相應庫,為編譯通過,選去掉它們
          libGLES_qcom.so
          liblvmxipc.so
          liboemcamera.so
          libstagefrighthw.so
          $ make
          $ cp device/htc/dream/wlan.ko out/target/product/dream/system/lib/modules/wlan.ko
          #網卡驅動
          $ make snod        
          重新生成system.img

          三、 把編譯好的軟件燒寫到手機

          usb線連接手機到電腦,按home+power鍵將手機啟動到工程模式,按back鍵準備燒寫
          $ export PATH=$PATH:$ANDROID/out/host/linux-x86/bin        #
          把燒寫工具所在目錄加上路徑
          $ cd out/target/product/dream/
          $ fastboot flash system system.img
          $ fastboot flash boot boot.img
          $ fastboot reboot

          燒寫系統后第一次啟動手機需要幾分鐘,請耐心等

          四、 修改

          1.        安裝中文字體(可以在燒寫前加入,加在此處用以說明在啟動后修改系統的方法)
          $ adb shell
          # su            
          取得root權限

          # mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system    
          使system分區可寫
          # chmod 777 /system/fonts     
          使某個目錄有寫權限
          # exit
          # exit
          $ adb push frameworks/base/data/fonts/DroidSansFallback.ttf /system/fonts/         
          加中文字體
          $ adb reboot

          2.        支持GPRS上網
          添加APN即可上網和發彩信,詳見http://www.andbeta.com/Basics/678.html

          3.        設置帳戶
          添加帳戶時,服務器填寫m.google.com

          五、 參考

          1.        刷寫部分未詳細描述,具體請參考文檔
          http://xy0811.spaces.live.com/blog/cns!F8AECD2A067A6B17!1452.entry

          2.        源碼編譯部分未詳細描述,具體請參考文檔
          http://xy0811.spaces.live.com/blog/cns!F8AECD2A067A6B17!1364.entry


          轉自:http://blog.csdn.net/xieyan0811/article/details/5931573

          posted @ 2011-09-04 11:03 馬航 閱讀(409) | 評論 (0)編輯 收藏

          在android的設計中,谷歌設計了一套專門為嵌入式設備使用的bionic C庫,以替換原有的GUN Libc,這個精簡的bionic庫據說只有200多K,所以如果只想使用這個精簡的C庫像在linux下一樣 開發C程序,基本是不可能的。當然如果只想讓其在shell中運行還是可以做到的。

          因為編譯完的目標程序是在android下運行,就要使用交叉編譯的工具,在下面地址下載:

          http://www.codesourcery.com/gnu_toolchains/arm/download.html

          下載完之后,bin目錄下的arm-none-linux-gnueabi-gcc就是交叉編譯器了

          #include <stdio.h>
          int main() {
          	printf("nihao a\n");
          	printf("你好 啊\n");
          	return 1;
          }
          

          輸入一下命令:

          ./arm-none-linux-gnueabi-gcc hello.c -o hello -static

          -static選項在這里是必須的,否則會出現”not found”的錯誤。

          然后就可以把編譯好的hello傳到手機上運行了。不過這里有個前提條件,要求android機器必須是root過的,好像簡單的z4root還不行,必須使用更徹底的root方法,關于如何root,這里就不再贅述了,可以參考相關root的帖子。

          adb push hello /dev/sample/

          這里要上傳的目錄必須是root用戶所有的。

          然后就是運行程序,可以在adb shell里測試

          adb shell

          cd /dev/sample/

          chmod 777 hello

          ./hello

          或者在手機上安裝超級終端,在終端里運行

          ./hello

          posted @ 2011-09-02 09:43 馬航 閱讀(241) | 評論 (0)編輯 收藏

          http://bbs.hiapk.com/thread-553691-1-1.html

          在ubuntu下adb找不到設備的解決方法:

          需要在Windows下鎖定端口就好了

          在adb shell中輸入如下命令:

          echo 22>/sys/devices/platform/msm_hsusb_periphera/fixusb 

          posted @ 2011-09-01 17:20 馬航 閱讀(136) | 評論 (0)編輯 收藏

          一、使用git下載android內核部分源碼

          首先新建要保存android內核源碼的目錄

          mkdir android_kernel

          cd android_kernel

          android kernel的網站http://android.git.kernel.org/

          git clone git://android.git.kernel.org/kernel/common.git

          下載android內核源碼,完成之后會看到common目錄,內核的源碼就算下載完成了

          如果想下載某一內核的版本,可以使用下面幾個命令:

          git branch -a // 顯示所有的分支

          git branch -r // 顯示romote端的分支

          git checkout // 檢出某一分支

          二、設置交叉編譯環境

          交叉編譯的環境在android源碼已經存在,源碼的下載可以參考《下載編譯android源碼》。在源碼目錄的android_source/prebuilt/linux-x86/toolchain/,可以看到多個交叉編譯的工具

          mac@mac-desktop:~/works/android_dev/prebuilt/linux-x86/toolchain$ ls -all

          總用量 44

          drwxr-xr-x 9 mac mac 4096 2011-08-28 15:16 arm-eabi-4.2.1

          drwxr-xr-x 9 mac mac 4096 2011-08-28 15:16 arm-eabi-4.3.1

          drwxr-xr-x 10 mac mac 4096 2011-08-28 15:16 arm-eabi-4.4.0

          drwxr-xr-x 10 mac mac 4096 2011-08-28 15:16 arm-eabi-4.4.3

          drwxr-xr-x 10 mac mac 4096 2011-08-28 15:16 arm-linux-androideabi-4.4.x

          drwxr-xr-x 6 mac mac 4096 2011-08-28 15:16 i686-android-linux-4.4.3

          drwxr-xr-x 8 mac mac 4096 2011-08-28 15:17 i686-linux-glibc2.7-4.4.3

          drwxr-xr-x 10 mac mac 4096 2011-08-28 15:17 i686-unknown-linux-gnu-4.2.1

          drwxr-xr-x 6 mac mac 4096 2011-08-28 15:17 sh-4.3.3

          一般使用最新版本。

          三、配置編譯時的config文件

          因為編譯的鏡像是要刷到模擬器運行的,模擬器的處理器架構是基于goldfish,所以需要下載有關goldfishconfig文件。下載方法:

          mac@mac-desktop:~/works/kernel-2.6.29$ git branch -a

          * (no branch)

          android-2.6.29

          android-2.6.36

          remotes/origin/HEAD -> origin/android-2.6.36

          remotes/origin/android-2.6.35

          remotes/origin/android-2.6.36

          remotes/origin/android-2.6.37

          remotes/origin/android-2.6.38

          remotes/origin/android-2.6.39

          remotes/origin/android-3.0

          remotes/origin/archive/android-2.6.25

          remotes/origin/archive/android-2.6.27

          remotes/origin/archive/android-2.6.29

          remotes/origin/archive/android-2.6.32

          remotes/origin/archive/android-gldfish-2.6.29

          remotes/origin/archive/android-goldfish-2.6.27

          remotes/origin/linux-bcm43xx-2.6.39

          remotes/origin/linux-wl12xx-2.6.39

          下載remotes/origin/archive/android-gldfish-2.6.29 版本:

          git checkout origin/archive/android-gldfish-2.6.29

          然后就可以到arch/arm/configs下看到goldfish_defconfig這個文件了。

          goldfish_defconfig文件拷貝到android_kernel目錄,并重命名為.config

          四、make編譯

          首先設置環境:

          export PATH=$PATH:~/android_source/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin

          然后修改Makefile

          ARCH = arm #體系結構為arm

          CROSS_COMPILE = arm-eabi- #交叉編譯工具鏈前綴,參考/toolchain/arm-eabi-4.4.3/bin

          然后就可以make編譯了,編譯過程中會連續提示yes/not,能看懂的多注意幾眼,看不懂的一路狂按Enter,最后如果前面的設置正確,編譯完整后會看到下面的提示:

          OBJCOPY arch/arm/boot/zImage

          Kernel: arch/arm/boot/zImage is ready

          五、編譯得到zImage,用新內核啟動模擬器

          ./emulator -avd android2.1 -kernel ~/kernel-2.6.29/arch/arm/boot/zImage

          在模擬器上查看系統信息:

          posted @ 2011-09-01 14:19 馬航 閱讀(1352) | 評論 (0)編輯 收藏

          現在使用linux的朋友越來越多了,在linux下做開發首先就是需要配置環境變量,下面以配置java環境變量為例介紹三種配置環境變量的方法。

           

          1.修改/etc/profile文件

          如果你的計算機僅僅作為開發使用時推薦使用這種方法,因為所有用戶的shell都有權使用這些環境變量,可能會給系統帶來安全性問題。

           

          (1)用文本編輯器打開/etc/profile

           

          (2)在profile文件末尾加入:

          JAVA_HOME=/usr/share/jdk1.5.0_05

          PATH=$JAVA_HOME/bin:$PATH

          CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

          export JAVA_HOME

          export PATH

          export CLASSPATH

           

          (3)重新登錄

           

          注解:

          a. 你要將 /usr/share/jdk1.5.0_05jdk 改為你的jdk安裝目錄

           

          b. linux下用冒號“:”來分隔路徑

           

          c. $PATH / $CLASSPATH / $JAVA_HOME 是用來引用原來的環境變量的值,在設置環境變量時特別要注意不能把原來的值給覆蓋掉了,這是一種常見的錯誤。

           

          d. CLASSPATH中當前目錄“.”不能丟,把當前目錄丟掉也是常見的錯誤。

           

          e. export是把這三個變量導出為全局變量。

           

          f. 大小寫必須嚴格區分。

           

          2. 修改.bashrc文件  

          這種方法更為安全,它可以把使用這些環境變量的權限控制到用戶級別,如果你需要給某個用戶權限使用這些環境變量,你只需要修改其個人用戶主目錄下的.bashrc文件就可以了。

           

          (1)用文本編輯器打開用戶目錄下的.bashrc文件

           

          (2)在.bashrc文件末尾加入:  

          set JAVA_HOME=/usr/share/jdk1.5.0_05

          export JAVA_HOME

          set PATH=$JAVA_HOME/bin:$PATH

          export PATH

          set CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

          export CLASSPATH

           

          (3)重新登錄

           

          3. 直接在shell下設置變量

          不贊成使用這種方法,因為換個shell,你的設置就無效了,因此這種方法僅僅是臨時使用,以后要使用的時候又要重新設置,比較麻煩。

           

          只需在shell終端執行下列命令:

          export JAVA_HOME=/usr/share/jdk1.5.0_05

          export PATH=$JAVA_HOME/bin:$PATH

          export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

          posted @ 2011-09-01 11:21 馬航 閱讀(135) | 評論 (0)編輯 收藏

          剛開始學著用linux,對vi命令不是很熟,在網上轉接了一篇。

          vi編輯器是所有Unix及Linux系統下標準的編輯器,它的強大不遜色于任何最新的文本編輯器,這里只是簡單地介紹一下它的用法和一小部分指 令。由于 對Unix及Linux系統的任何版本,vi編輯器是完全相同的,因此您可以在其他任何介紹vi的地方進一步了解它。Vi也是Linux中最基本的文本編 輯器,學會它后,您將在Linux的世界里暢行無阻。

          1、vi的基本概念
            基本上vi可以分為三種狀態,分別是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能區分如下:
              1) 命令行模式command mode)
            控制屏幕光標的移動,字符、字或行的刪除,移動復制某區段及進入Insert mode下,或者到 last line mode。
              2) 插入模式(Insert mode)
            只有在Insert mode下,才可以做文字輸入,按「ESC」鍵可回到命令行模式。
              3) 底行模式(last line mode)
            將文件保存或退出vi,也可以設置編輯環境,如尋找字符串、列出行號……等。
           
              不過一般我們在使用時把vi簡化成兩個模式,就是將底行模式(last line mode)也算入命令行模式command mode)。
          2、vi的基本操作 
          a) 進入vi
              在系統提示符號輸入vi及文件名稱后,就進入vi全屏幕編輯畫面:
             $ vi myfile
          不過有一點要特別注意,就是您進入vi之后,是處于「命令行模式(command mode)」,您要切換到「插入模式(Insert mode)」才能夠輸入文字。初次使用vi的人都會想先用上下左右鍵移動光標,結果電腦一直嗶嗶叫,把自己氣個半死,所以進入vi后,先不要亂動,轉換到 「插入模式(Insert mode)」再說吧!
           
          b) 切換至插入模式(Insert mode)編輯文件
            在「命令行模式(command mode)」下按一下字母「i」就可以進入「插入模式(Insert mode)」,這時候你就可以開始輸入文字了。
           
          c) Insert 的切換
            您目前處于「插入模式(Insert mode)」,您就只能一直輸入文字,如果您發現輸錯了字!想用光標鍵往回移動,將該字刪除,就要先按一下「ESC」鍵轉到「命令行模式(command mode)」再刪除文字。
           
          d) 退出vi及保存文件
            在「命令行模式(command mode)」下,按一下「:」冒號鍵進入「Last line mode」,例如:
          : w filename (輸入 「w filename」將文章以指定的文件名filename保存)
          : wq (輸入「wq」,存盤并退出vi)
          : q! (輸入q!, 不存盤強制退出vi)

          3、命令行模式(command mode)功能鍵
          1). 插入模式
                 按「i」切換進入插入模式「insert mode」,按"i"進入插入模式后是從光標當前位置開始輸入文件;
            按「a」進入插入模式后,是從目前光標所在位置的下一個位置開始輸入文字;
            按「o」進入插入模式后,是插入新的一行,從行首開始輸入文字。
           
          2). 從插入模式切換為命令行模式
                按「ESC」鍵。
           
          3). 移動光標
            vi可以直接用鍵盤上的光標來上下左右移動,但正規的vi是用小寫英文字母「h」、「j」、「k」、「l」,分別控制光標左、下、上、右移一格。
            按「ctrl」+「b」:屏幕往"后"移動一頁。
            按「ctrl」+「f」:屏幕往"前"移動一頁。
            按「ctrl」+「u」:屏幕往"后"移動半頁。
            按「ctrl」+「d」:屏幕往"前"移動半頁。
            按數字「0」:移到文章的開頭。
            按「G」:移動到文章的最后。
            按「$」:移動到光標所在行的"行尾"。
            按「^」:移動到光標所在行的"行首"
            按「w」:光標跳到下個字的開頭
            按「e」:光標跳到下個字的字尾
            按「b」:光標回到上個字的開頭
            按「#l」:光標移到該行的第#個位置,如:5l,56l。
           
          4). 刪除文字
            「x」:每按一次,刪除光標所在位置的"后面"一個字符。
            「#x」:例如,「6x」表示刪除光標所在位置的"后面"6個字符。
            「X」:大寫的X,每按一次,刪除光標所在位置的"前面"一個字符。
            「#X」:例如,「20X」表示刪除光標所在位置的"前面"20個字符。
            「dd」:刪除光標所在行。
            「#dd」:從光標所在行開始刪除#行
           
          5). 復制
            「yw」:將光標所在之處到字尾的字符復制到緩沖區中。
            「#yw」:復制#個字到緩沖區
            「yy」:復制光標所在行到緩沖區。
            「#yy」:例如,「6yy」表示拷貝從光標所在的該行"往下數"6行文字。
            「p」:將緩沖區內的字符貼到光標所在位置。注意:所有與"y"有關的復制命令都必須與"p"配合才能完成復制與粘貼功能。
           
          6). 替換
            「r」:替換光標所在處的字符。
            「R」:替換光標所到之處的字符,直到按下「ESC」鍵為止。
           
          7). 回復上一次操作
            「u」:如果您誤執行一個命令,可以馬上按下「u」,回到上一個操作。按多次"u"可以執行多次回復。
           
          8). 更改
            「cw」:更改光標所在處的字到字尾處
            「c#w」:例如,「c3w」表示更改3個字
           
          9). 跳至指定的行
            「ctrl」+「g」列出光標所在行的行號。
            「#G」:例如,「15G」,表示移動光標至文章的第15行行首。

          4、Last line mode下命令簡介
          在使用「last line mode」之前,請記住先按「ESC」鍵確定您已經處于「command mode」下后,再按「:」冒號即可進入「last line mode」。

          A) 列出行號

           「set nu」:輸入「set nu」后,會在文件中的每一行前面列出行號。

          B) 跳到文件中的某一行

           「#」:「#」號表示一個數字,在冒號后輸入一個數字,再按回車鍵就會跳到該行了,如輸入數字15,再回車,就會跳到文章的第15行。

          C) 查找字符

           「/關鍵字」:先按「/」鍵,再輸入您想尋找的字符,如果第一次找的關鍵字不是您想要的,可以一直按「n」會往后尋找到您要的關鍵字為止。

           「?關鍵字」:先按「?」鍵,再輸入您想尋找的字符,如果第一次找的關鍵字不是您想要的,可以一直按「n」會往前尋找到您要的關鍵字為止。

          D) 保存文件

           「w」:在冒號輸入字母「w」就可以將文件保存起來。

          E) 離開vi

           「q」:按「q」就是退出,如果無法離開vi,可以在「q」后跟一個「!」強制離開vi。

           「qw」:一般建議離開時,搭配「w」一起使用,這樣在退出的時候還可以保存文件。

          5、vi命令列表
          1、下表列出命令模式下的一些鍵的功能:

          h
          左移光標一個字符

          l
          右移光標一個字符

          k
          光標上移一行

          j
          光標下移一行

          ^
          光標移動至行首

          0
          數字"0",光標移至文章的開頭

          G
          光標移至文章的最后

          $
          光標移動至行尾

          Ctrl+f
          向前翻屏

          Ctrl+b
          向后翻屏

          Ctrl+d
          向前翻半屏

          Ctrl+u
          向后翻半屏

          i
          在光標位置前插入字符

          a
          在光標所在位置的后一個字符開始增加

          o
          插入新的一行,從行首開始輸入

          ESC
          從輸入狀態退至命令狀態

          x
          刪除光標后面的字符

          #x
          刪除光標后的#個字符

          X
          (大寫X),刪除光標前面的字符

          #X
          刪除光標前面的#個字符

          dd
          刪除光標所在的行

          #dd
          刪除從光標所在行數的#行

          yw
          復制光標所在位置的一個字

          #yw
          復制光標所在位置的#個字

          yy
          復制光標所在位置的一行

          #yy
          復制從光標所在行數的#行

          p
          粘貼

          u
          取消操作

          cw
          更改光標所在位置的一個字

          #cw
          更改光標所在位置的#個字


          2、下表列出行命令模式下的一些指令
          w filename
          儲存正在編輯的文件為filename

          wq filename
          儲存正在編輯的文件為filename,并退出vi

          q!
          放棄所有修改,退出vi

          set nu
          顯示行號

          /或?
          查找,在/后輸入要查找的內容

          n
          與/或?一起使用,如果查找的內容不是想要找的關鍵字,按n或向后(與/聯用)或向前(與?聯用)繼續查找,直到找到為止。


          對于第一次用vi,有幾點注意要提醒一下:
          1、 用vi打開文件后,是處于「命令行模式(command mode)」,您要切換到「插入模式(Insert mode)」才能夠輸入文字。切換方法:在「命令行模式(command mode)」下按一下字母「i」就可以進入「插入模式(Insert mode)」,這時候你就可以開始輸入文字了。
          2、編輯好后,需從插入模式切換為命令行模式才能對文件進行保存,切換方法:按「ESC」鍵。
          3、保存并退出文件:在命令模式下輸入:wq即可!(別忘了wq前面的:)

          posted @ 2011-09-01 10:34 馬航 閱讀(153) | 評論 (0)編輯 收藏

            google的android很多人都希望在gphone沒有出來之前,把它移植到相關的硬件平臺上去。網上看了不少文章,總的感覺是:在這一步走得最遠的就是openmoko的一個大師級別的黑客Ben “Benno” Leslie,他曾經試圖把目前google發布的android移植到openmoko的平臺上去,并且做了10000多行代碼的嘗試。最終雖然由于 open moko采用比較老的arm 920t的內核,而android采用較新的arm926-ej-s內核,而且使用了新的內核的一些新特性,導致移植失敗,但是anyway,他已經做了足夠多的前期工作了,爾后的宣布成功移植android到real target板子上的人,大多是在他提供的patch的基礎上繼續走下去做出來的。

          下面是一些有用的參考,希望有助于對此感興趣的開發人員:
          (1)Ben “Benno” Leslie的關于andorid移植到openmoko的個人博客地址:
          http://benno.id.au/blog/

          (2)早期宣布成功移植android到zauraus-sl-c760的詳細方法描述的鏈接:
          http://euedge.com/blog/2007/12/06/google-android-runs-on-sharp-zaurus-sl-c760/

          (3)后續的根據上述先行者們的工作,成功移植android到zauraus-c3000的方法:
          http://androidzaurus.seesaa.net/article/74237419.html

          (4)本文是參考下面的wiki,接合個人的實踐寫出來的,對原文的作者表示一下感謝:
          http://wiki.droiddocs.net/Compilation_of_Android_kernel

            很羨慕這些人阿!

            不過很可惜,偶的開發板是s3c2410的,恰好是arm920t的核心的。。。估計移植上去戲不是很大,需要重寫很多代碼,畢竟偶跟benno相差得太遠太遠了,同樣是開發人員,差距咋就那么大呢?!(畢竟google僅僅開放了kernel的源代碼而已,他們需要開放的東西還很多。)

            在這里把關于android內核編譯方法簡單寫一下,或許對希望移植內核的朋友能有些幫助:
          (看了Benno的移植過程以后,覺得即使你能夠編譯google開放出來的內核,意義也不是特別大,因為這個內核中加入了為了支持qemu的很多東西,而這些代碼似乎對希望移植到真機上的朋友來說,沒有任何意義,反而是一種阻礙)。

            1)從CodeSourcery上面載用于交叉編譯的工具鏈:http://www.codesourcery.com/gnu_toolchains/arm/download.html
          我在這里選擇的是->ARM GNU/Linux,以及IA32-GNU/Linux。有文章說應該選擇ARM EABI,我不知道了,沒有測試過,反正我選擇的這個編譯的內核也是可以跑起來的:P

            2)下載google的android linux的內核源代碼:http://code.google.com/p/android/downloads/list
          主要是這個文件:linux-2.6.23-android-m3-rc20.tar.gz

            3)把下載到的內核和交叉編譯工具解壓縮,并最好把工具鏈的路徑放到PATH里面去
          解壓縮內核:
           $ mkdir -p android
           $ cd android
           $ tar xzvf ../linux-2.6.23-android-m3-rc20.tar.gz
           會解壓出來一個叫做kernel的目錄,google的android的linux內核就在里面了。

          解壓縮交叉編譯工具鏈:
           $ cd /usr/local/
           $ sudo cp ~/arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 .
           $ sudo tar zxvf arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
          此時會解壓出來一個叫做arm2007q3的一個目錄,這里面就是工具鏈了。

          設置一下環境變量:
           $ export PATH=$PATH:/usr/local/arm2007q3/bin
          好了,到此,基本的內核編譯環境就搞好了。

            4)現在是要得到android的內核編譯參數的配置文件的時候了,該文件需要從已經安裝好的android的模擬器
          中得到才行。所以安裝android的sdk也是必須的,這一步不太明白的朋友可以參考我以前發的android
          命令行體驗的文章。
          首先啟動android模擬器,然后通過adb得到模擬器中提供的內核配置文件:
           $emulator &
           $adb pull /proc/config.gz .
          這時候adb工具會連接模擬器,并從它里面下載一個叫做config.gz的文件到你的當前目錄下。
          把它拷貝到你的kernel目錄:
           $cd ~/android/kernel
           $cp ~/config.gz .
          解壓縮該文件,并重命名為.config,這一步做了就可以跳過make menuconfig之類的內核參數設置
          動作了。
           $gunzip config.gz
           $mv config .config

            5)修改kernel目錄中的Makefile文件,用emacs或vi打開該Makefile

          修改CROSS_COMPILE變量為:
          CROSS_COMPILE=arm-none-linux-gnueabi-
          這個就是剛剛的下載和解壓的工具鏈的前綴了,旨在告訴make,在編譯的時候要使用我們的工具鏈。

          在Makefile中注釋掉LDFLAGS_BUILD_ID這個變量:
          例如將如下定義:
          LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
                            $(call ld-option, -Wl$(comma)--build-id,))
          修改為:
          LDFLAGS_BUILD_ID=
          #LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
          #                  $(call ld-option, -Wl$(comma)--build-id,))
          把它注釋掉的原因是目前android的內核還不支持這個選項。--build-id選項,主要是用于在生成的elf
          可執行文件中加入一個內置的id,這樣在core dump,或者debuginfo的時候就可以很快定位這個模塊是
          哪次build的時候弄出來的。這樣就可以避免,每次都把整個文件做一遍效驗,然后才能得到該文件的是由
          哪次build產生的。對于內核開發者來說,這是很不錯的想法,可以節約定位模塊版本和其影響的時間。
          目前,該功能還出于early stage的狀態,未來的android或許會支持,但至少目前的版本是不支持的。
          所以,用#注釋掉即可,或者害怕不保險的話,就加入LDFLAGS_BUILD_ID=空,這樣即使編譯的時候用了,
          也只是一個空格而已。
          對這個--build-id選項感興趣的朋友,可以訪問下面的網址,它的作者已經解釋得非常明白了:
          http://fedoraproject.org/wiki/Releases/FeatureBuildId

            6)終于可以開始make了。
           $ make
          不出意外的話,應該整個過程都會非常順利,最終會在~/android/kernel/arch/arm/boot目錄下面
          生成一個zImage,這個就是我們要的內核映像了。

            7)激動人心的時刻終于到來了,我們可以測試一下剛剛編譯出來的內核可以不可以用了。
           $emulator -kernel ~/android/kernel/arch/arm/boot/zImage
          當看到red eye在晃來晃去,最終顯示出來android的界面的時候,一顆懸著的心總算放下了。

          android的proc里面的version如下:
          # cat version
          Linux version 2.6.23 (wayne@wayne) (gcc version 4.2.1 (CodeSourcery Sourcery G++ Lite 2007q3-51)) #1 Sat Jan 19 18:11:44 HKT 2008
          從這里就可以看出,這是自己編譯的kernel,而不是人家sdk里面自帶的kernel-qemu了。

          android自帶的sdk里面的kernel映像的version應該是:
          # cat version
          Linux version 2.6.23-gcc3bc3b4 (arve@arvelnx.corp.google.com) (gcc version 4.2.1) #3 Tue Oct 30 16:28:18 PDT 2007
          hoho, 這里不會把這個開發者的email暴露出來了吧。。。

          android的cpuinfo如下:
          Processor       : ARM926EJ-S rev 5 (v5l)
          BogoMIPS        : 313.75
          Features        : swp half thumb fastmult vfp edsp java
          CPU implementer : 0x41
          CPU architecture: 5TEJ
          CPU variant     : 0x0
          CPU part        : 0x926
          CPU revision    : 5
          Cache type      : write-through
          Cache clean     : not required
          Cache lockdown  : not supported
          Cache format    : Harvard
          I size          : 4096
          I assoc         : 4
          I line length   : 32
          I sets          : 32
          D size          : 65536
          D assoc         : 4
          D line length   : 32
          D sets          : 512

          Hardware        : Goldfish
          Revision        : 0000
          Serial          : 0000000000000000
          不過挺奇怪的,google sdk自帶的內核映像的BogoMIPS是3.18的,偶編譯出來的是3.13的。

          posted @ 2011-08-31 09:25 馬航 閱讀(464) | 評論 (0)編輯 收藏

          環境:

             windows xp+vmware+redhat(ubuntu)

             說明:本篇所述環境也是Android原生(Native)C(JNI)開發的環境

          1,先下載個交叉編譯工具鏈版本

            http://www.codesourcery.com/sgpp/lite/arm/portal/subscription3057 選擇最新版本進入下載頁面后,選擇Advanced Packages的IA32 GNU/Linux TAR下載后文件名為arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

          2,上傳到/usr/local/后解壓tar jxvf arm-2010.09-50-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 到一個arm-2010.09

          3,測試,進入到/usr/local/arm-2010.09/bin目錄下,創建一個main.c文件,

          main.c內容

          #include <stdio.h>

          int main()

          {

            int i=0;

            printf("%d\n",i);

            return;

          }

          執行./arm-none-linux-gnueabi-gcc main.c 

          無報錯,生成a.out文件

          執行 ./arm-none-linux-gnueabi-gcc -v

          顯示版本信息 4.5.1 

          可以啦

          修改/etc/profile文件的PATH,將當前目錄/usr/local/arm-2010.09-50/bin加入到PATH里去

          source /boot/.bashrc 使修改立即生效

          實例測試:

          進入工作目錄 /home/android/jniTest

          創建文件main.c,文件內容

          #include <stdio.h>
          int main()
          {
            int i=0;
            printf("hi ym012 %d\n",i);
            return;
          }

          arm-none-linux-gnueabi-gcc -static main.c -o main
          啟動Android模擬器,先創建 /dev/sample目錄,再將編譯好的main上傳上去,最后將main改成可執行的。其命令如下

          adb shell mkdir /dev/sample                        //在模擬器下創建一個目錄
          adb push main /dev/sample/main                //將main文件上傳到/dev/sample/main

          adb shell chmod 777 /dev/sample/main      //修改成可執行文件

           再進入命令行模式,進入Android的模擬器的/dev/sample目錄執行hello:

          adb shell

          #cd /dev/sample

          #./hello                          //執行hello

          運行結果如下:

          hi ym012 0
          _______________

          總結:成功了!

          posted @ 2011-08-31 09:14 馬航 閱讀(571) | 評論 (0)編輯 收藏

              最近不單只是看android開發與測試相關知識,也在了解這之外相關的信息.畢竟,自己的眼界不能太狹窄.今天我在逛一個android論壇上時候看到一個很老的帖子,轉了個關于android被從linux分支樹上移除的新聞.
              以為是假新聞來著,后面上網找了找,還真是搜索出一堆結果,發現有些比較大的IT網站上也有.看樣子是假不了了.
              原文上說是linux內核開發者Greg Kroah-Hartman認為android"no one seemed to be working on it"
              想著android系統實際上使用了linux內核,而linux講究的是開源,android雖然開源,確實商用的.中間可能有沖突的地方.難道是其中某些沖突引起了這樣的結果?
              最后在維基百科上android詞條(http://zh.wikipedia.org/wiki/Android)頁面的結尾部分找到了這么一段:
              "
              Android是執行于Linux kernel之上,但并不是GNU/Linux。因為在一般GNU/Linux里支持的功能,Android大都沒有支持,包括Cairo、X11、 Alsa、FFmpeg、GTK、Pango及Glibc等都被移除掉了。Android又以bionic取代Glibc、以Skia取代Cairo、再 以opencore取代FFmpeg等等。Android為了達到商業應用,必須移除被GNU GPL授權證所約束的部份,例如Android將驅動程序移到userspace,使得Linux driver與Linux kernel徹底分開。bionic/libc/kernel/ 并非標準的kernel header files。Android的kernel header是利用工具由Linux kernel header所產生的,這樣做是為了保留常數、資料結構與宏。
              "
              可見,從最直觀上來看,android將linux內核拿過來之后去掉了不少功能,然后通過一些手段繞開了GPL授權.它的linux內核已經和GNU Linux相差的太大了.然而,更具體的情況是什么樣的呢?即android被移出linux分支樹的更具體的說明.

              終于找到了,摘抄在后面(摘自:http://www.ej38.com/showinfo/linux-199996.html)
          -----------------------------------------------------------------------------------------------------------------------------------------------------
              Greg Kroah-Hartman寫了一篇詳細的文章,解釋這個決定。下面就來看看,他是怎么說的,以及Android到底是一個什么樣的系統。
              在這之前,你最好知道Greg Kroah-Hartman是誰。他是目前LinuxKernel的核心開發人員,負責stable軟件包的發布。就是說,每一個新版本的 LinuxKernel,都是經過他的手流出來的。此外,他還負責硬件驅動的部署。而他的手機就是HTCG1,每天都在使用。所以,他是絕對有資格談論這 個問題的,他的看法代表了Linux社區對Android的看法。
              首先,他指出Android和其他的Linux發行版不一樣:
          “Google has taken the Linux kernel, and nothing else from a "traditional" Linux system. Google只用了kernel,別的東西都沒用。”
              這就是說,與Ubuntu、Debian、Redhat這樣的傳統Linux發行版相比,只有系統的底層結構是一樣的,其他東西在Android里都不一 樣,尤其是程序員的編程接口是完全不同的。因此,Android應用程序都必須重新寫過,現存的Linux程序無法移植上去。所以,從嚴格意義上 說,Android是一種全新的系統,它與Linux的距離,比Mac OS與Linux的距離還要遠。
              然后,Greg Kroah-Hartman肯定了Android這樣做的積極意義:
          “Android also solves the problem that the phone manufacturers hadbeen having for many years: a free version of Java and a unifiedapplication layer that programmers can write to that will work on allphone platforms that integrate it.
          它解決了長期令手機制造商頭痛不已的問題:業界缺乏一個開源的Java虛擬機,以及統一的應用程序接口。現在,程序員只要寫一次程序,就能在各種手機硬件平臺之上使用。”
              這段話解釋了,為什么Android的應用程序,都必須用Java語言開發。因為不這樣做的話,沒法讓程序做到硬件無關。且慢,這真的是理由嗎?傳統的 Linux系統,也并不依賴特定的硬件啊!只要把源代碼根據不同的平臺,分別編譯一下,同一個程序不也照樣可以在不同的硬件架構、不同的Linux發行版 中使用嗎?那么,Android只采用kernel、只允許用java編程的真正原因,到底是什么?
              臺灣的科技網志MMDays一語道破真相:“Linux kernel 的版權是 GPL。這下問題來了:如果你是硬件廠商,希望你的硬件能在 Linux kernel 下運作,那么就必須要有驅動程序。如果驅動程序的程序代碼公開,等于硬件規格也公開的差不多了。許多廠商不愿意這么做,所以就提供編好的驅動程序,但不提 供原始碼。Android 的重點就是商業應用,Google采用了一些手法來繞過這問題。他們把驅動程序移到"userspace",也就是說,把驅動程序變成在 Linux kernel 上頭跑,而不是一起跑的東西,這樣就可以避過GPL。然后,在kernel 這邊開個小門,讓本來不能直接控制到硬件的 "userspace" 程序也可以碰得到,這樣只要把"開個小門"的程序代碼公布就行啦。”看明白了嗎?
              這段話的意思是說,Google玩了一個花招,在kernel和應用程序之間,自己做了一個中間層,這樣就既不違反GPL許可,又能不讓外界看到廠商的硬件驅動和應用程序的源碼。
              里面的關鍵在于,Kernel和Android的許可證不一樣,前者是GPL許可證,后者是Apache SoftwareLicense(簡稱ASL)許可證。GPL許可證規定,對源碼的任何修改都必須開源,所以Android開源了,因為它修改了 Kernel。而ASL許可證規定,可以隨意使用源碼,不必開源,所以建筑在Android之上的硬件驅動和應用程序,都可以保持封閉。為了得到更多廠商 的支持,Google有意選擇了這樣做,并且特意修改Kernel,使得原本應該包括在kernel中的某些功能,都被轉移到了userspace之中, 因此得以避開開源。
              這樣做或許有利于推廣Android,吸引廠商和軟件開發商的加入,但是Google也放棄了構建一個真正開源的手機系統的機會,從而也就不能獲得由全世 界程序員提供智慧、分享代碼、推動創新的好處。關于許可證問題的深入討論,請閱讀Ryan Paul的文章《Why Google chose the Apache Software License over GPLv2 for Android》。
              Google的這種做法,直接后果就是給Linux Kernel帶來了麻煩。Greg Kroah-Hartman清楚地說出了自己的不滿。
          “...any drivers written for Android hardware platforms, can not getmerged into the main kernel tree because they have dependencies on codethat only lives in Google's kernel tree, causing it to fail to build inthe kernel.orgtree.所有為Android寫的硬件驅動,都不能合并入kernel。因為它們只在Google的代碼里有效,在kernel里 根本沒法用。
              Because of this, Google has now prevented a large chunk of hardwaredrivers and platform code from ever getting merged into the main kerneltree. Effectively creating a kernel branch that a number of differentvendors are now relying on.由于這個原因,Google也從不把大量的硬件驅動程序和平臺源碼向kernel提交。實際上,它創造出了一個kernel的分支,大量的開發者都 依賴那個分支。”
              這就是Android干的事情:它修改了Kernel,但是又不提供修改的細節,自己搞了一個封閉的系統。說得難聽一點,它利用了開源社區,要求開源社區為它做貢獻,卻又不愿提供回報。
              所以,Linux Kernel就把Android踢出去了,真是再正常不過了。
              人們有權利質疑,Android這樣的哲學是否正確?是否符合Google“不作惡”的口號?如果Android繼續這樣封閉下去,那么開源社區為什么要 為它免費制作軟件呢?因為我又不是在為開源社區服務,而是在為Google服務。既然這樣的話,那還不如去支持iPhone呢,至少能在軟件商店里多賣一 點錢,而且喬布斯看上去也更酷一點。slashdot上有很多關于此事的討論。有人指出:“Google自己的網站,與微軟的網站一樣封閉。它開源出來的 東西,都是根據GPL許可證不得不開源的。”
              好吧,姑且不談Google本身,因為它至少不要求外界提供支持。但是Android不一樣,你不能假裝成開源系統,騙取社區的支持,然后又干著封閉系統的勾當。
              Google必須做出選擇。正如Greg Kroah-Hartman最后的呼吁:
              “I really don't know. Google shows no sign of working to get their code upstream anymore.
          我真的不知道未來。Google看上去沒有任何改變代碼的跡象。
              I do hold out hope that Google does come around and works to fixtheir codebase to get it merged upstream to stop the huge blockage thatthey have now caused in a large number of embedded Linux hardwarecompanies. 我確實希望Google做出改變,把它的代碼合并進我們的代碼,彌補已經出現的代碼分裂。
              I've privately offered in the past to help this work get done, andam doing again here publicly. But I need the help of the Googledevelopers to make it happen, without them, nothing can change. 我私底下已經說過,我愿意幫助完成這項工作,在這里我再次公開這樣說。但是如果沒有Google程序員的加入,什么也不會發生。”

          posted @ 2011-08-29 13:39 馬航 閱讀(289) | 評論 (0)編輯 收藏

          細心的網友可能發現Android的 ROM中有很多odex文件,相對于APK中的dex文件而言這個odex有什么作用呢? Android123提示大家,如果你仔細觀察會發現文件名時一一對應的,同時那些對應的apk文件中沒有dex文件。這樣做可以使其廠商保證一定的反盜 版,因為沒有沒有dex文件的apk是無法正常安裝的,而廠商直接將odex和不完整的apk文件放到手機rom固化到/system/bin中可以讓一般用戶無法正常導出使用。

            很多網友可能想到的是合并odex和apk變成apk中包含dex文件的,這樣合并后最終apk文件安裝在/data/中,而rom存放時在 /system/bin中,所以最終導致了用戶可裝在Android手機中的軟件會變少,占用系統空間。

            一、APK生成odex文件方法:

            編譯開源GIT上的build/tools/dexpreopt/dexopt-wrapper這個,使用dexopt-wrapper即可,操作步驟

            將dexopt-wrapper放到/data/local目錄中,使用adb shell執行linux命令行,使用cd命令進入/data/local目錄,

            cd /data/local

            ./dexopt-wrapper android123.apk android123.odex

          二、合并odex和 少dex的apk 為完整的apk文件

            1. 下載 http://smali.googlecode.com/files/smali-1.2.2.jarhttp://smali.googlecode.com/files/baksmali-1.2.2.jar,既然是需要盜版,還需要odex所在rom中的一些引用類,一般在 /system/framework 目錄中

            2 .  通過odex生成class文件

                    java -jar baksmali-1.2.2.jar -x android123.odex

                  執行完上面這行命令后,會生成一個out 文件夾里面是android123.odex的class文件。出現問題,根據提示可以從rom的 /system/framework 中的xxx.jar放到pc上的java環境變量中一起生成。

            3. 通過class生成classes.dex 文件。

                  java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex

            4. 將classes.dex放到apk文件

                  因為apk是zip的mime編碼類型,使用winzip或winrar直接拖入到apk改名為zip的壓縮包中即可。

            5. 不要忘記了簽名,使用jdk中的arsigner和keytool打包重新簽名即可。

          posted @ 2011-08-28 15:22 馬航 閱讀(590) | 評論 (0)編輯 收藏

          安裝步驟(需要自己編譯):

          A. 獲取代碼:(沒有git的先安裝git:sudo apt-get install git-core)

          $ git clone git://github.com/tchaikov/scim-googlepinyin.git

          $ cd scim-googlepinyin

          B. 編譯前提:

          上面給的鏈接里面有介紹怎么編譯的,但少提了幾個必需組件,這里列一下:

          * autotools-dev

          * libgtk2.0-dev

          * libscim-dev

          * libtool

          * automake

          用下面命令看看是不是安裝了,如果沒有,會自動幫你安裝上:

          $ aptitude install autotools-dev libgtk2.0-dev libscim-dev libtool automake

          C. 編譯:

          記住系統必須先存在SCIM(沒有的話 sudo apt-get install scim 一下)

          $ ./autogen.sh

          $ make

          $ sudo make install

          現在重啟

          OK,去首選項里的“語言支持”的“輸入法”選擇scim作為默認輸入法就OK了。

          posted @ 2011-08-25 10:27 馬航 閱讀(145) | 評論 (0)編輯 收藏

          在編譯過程中出現錯誤信息包含以下內容:

          usr/share/pc-bios/bios.bin   …………      tools/lib/pc-bios/bios.bin

          usr/share/pc-bios/vgabios-cirrus.bin   …………     tools/lib/pc-bios/vgabios-cirrus.bin

          說明在路徑:~/Android_Src/out/host/linux-x86/usr/share下找不到pc-bios文件夾,并不是在本機系統目錄/usr/share……下找不到該文件夾,本機系統這個目錄下的確沒有的。

          解決方法為:

          復制:~/Android_Src/prebuilt/common下的pc-bios文件夾到以下目錄:~/Android_Src/out/host/linux-x86/usr/share即可解決,命令行輸入:

          $cp ~/Android_Src/prebuilt/common/pc-bios   ~/Android_Src/out/host/linux-x86/usr/share  (測試未通過)

          $cp ~/Android_Src/prebuilt/common/pc-bios   ~/Android_Src/usr/share  (測試OK)

          在編譯的過程中又出現如下提示:

          ……………………

          Docs droiddoc: out/target/common/docs/online-sdk

          htmlDir not a directory: out/target/common/docs/gen

          DroidDoc took 105 sec. to write docs to out/target/common/docs/online-sdk

          Package SDK: out/host/linux-x86/sdk/android-sdk_eng.neo_linux-x86.zip

          sdk/build/tools.atree:134: couldn't locate source file: framework/ddmlib-tests.jar

          sdk/build/tools.atree:135: couldn't locate source file: framework/ninepatch-tests.jar

          sdk/build/tools.atree:136: couldn't locate source file: framework/common-tests.jar

          sdk/build/tools.atree:138: couldn't locate source file: framework/sdkuilib-tests.jar

          make: *** [out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86.zip] Error 44

          大概的意思在framework目錄下找不到ddmlib-tests.jar     ninepath-tests.jar     common-tests.jar     sdkuilib-tests.jar這幾個文件,有一點要說明的是這里的framework目錄指的是:~/Android_Src/out/host/linux-x86/framework   個目錄,你可以在這里找到以下幾個文件common.jar     ddmlib.jar     ninepatch.jar     sdkuilib.jar,然后將它們分別復制一份,并重命名,命名的原則很簡單,就是在原有的名字后面跟上-tests即可。

          接下來繼續編譯,沒有其他錯誤的話,命令行會出現以下提示:

          Docs droiddoc: out/target/common/docs/online-sdk

          htmlDir not a directory: out/target/common/docs/gen

          DroidDoc took 90 sec. to write docs to out/target/common/docs/online-sdk

          Package SDK: out/host/linux-x86/sdk/android-sdk_eng.neo_linux-x86.zip

          xxx@xxx:~/Android_Src$ 

          這說明sdk編譯也已經完成。

          posted @ 2011-08-20 10:09 馬航 閱讀(1104) | 評論 (0)編輯 收藏

          前言

          本文敘述了如何從零開始搭建基于 Google 官方 Android 2.1-r2 源碼的開發環境,包括如何下載源代碼、編譯源代碼,以及在模擬器中運行編譯生成的鏡像。文中開發機是基于 Ubuntu 10.04 的,同樣適用于其他版本的 Ubuntu 。

              2. 下載 JDK 1.5

          編譯 Android 源碼需要 JDK1.5 版(主要是需要其中的 javadoc ), 1.6 版是不兼容的。 JDK1.5 已經停止支持,其最終的版本是 JDK 5.0 Update 22 。

          可從 Sun 官網上下載:

          http://java.sun.com/javase/downloads/5u22/jdk

          選擇平臺 Linux ,勾選同意許可協議:

          單擊 Continue ,在彈出的頁面中一共有兩個下載,選第一個 jdk-1_5_0_22-linux-i586.bin 下載:

                   3. 部署 JDK 1.5

                     3.1 解壓縮 JDK

          以下命令均在 root 賬戶上執行,非 root 賬戶執行某些命令可能需要加 sudo 。

          將 jdk-1_5_0_22-linux-i586.bin 放在 root 目錄下。進入該目錄:

          cd ~

          然后賦予該 bin 文件可執行屬性:

          chmod +x jdk-1_5_0_22-linux-i586.bin

          再執行安裝 ( 注意前面有 ./) :

          ./jdk-1_5_0_22-linux-i586.bin

          跳過協議閱讀。

          最后一行:

          Do you agree to the above license terms? [yes or no]

          鍵入 yes ,然后回車,開始解壓。默認會解壓到當前目錄下的 jdk1.5.0_22 目錄下(此處是 ~/ jdk1.5.0_22 )。

                     3.2 JDK 版本切換

          如果同時需要使用 JDK1.6 版做應用開發,則系統中將同時存在 JDK1.5 和 JDK1.6 。因此需要實現能夠在不同版本間切換。如果不使用 JDK1.6 ,請做完 1.5 版的設置后跳至 3.3 節。

          這里使用 update-alternatives 命令實現。

          首先為 JDK1.5 版生成可選配置選項:

          update-alternatives --install /usr/bin/jdk jdk /root/jdk1.5.22 255

          /usr/bin/jdk 是符號鏈接,它指向 /etc/alternatives/jdk (由第 2 個參數給出的), /root/jdk1.5.22 是實際目的鏈接, 255 是優先級(任意整數,在 automatic mode 自動模式時,數字大的優先級較高,被選為默認配置選項)。

          然后再為 JDK1.6 版生成( 如果有 JDK1.6 的話。不使用 JDK1.6 的請跳至 3.3 節 ):

          update-alternatives --install /usr/bin/jdk jdk /root/jdk1.6.20 0

          這樣,默認 jdk 版本即為 1.5 版。需要切換到 1.6 版時,請使用 update-alternatives –config jdk

                     3.3 配置 JDK 環境變量

          下面開始配置環境變量。

          在終端中執行: gedit ~/.bashrc

          修改 .bashrc 文件,添加下面語句:

          #set java environment

          export JAVA_HOME=/usr/bin/jdk

          export JRE_HOME=JAVA_HOME/jre

          export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH

          export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

          該段代碼最好設置在文件的尾部。

          保存文件。在終端中執行 source ~/.bashrc

          請使用 java – version 檢查 JDK 是否配置正確。

                  4. 安裝其他必備組件

          在終端上,使用下面的命令安裝:

          apt-get install git-core gnupg flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev

          因為 JDK1.5 在前面已經單獨安裝過了,因此此處 apt-get install 命令行中沒有加入 sun-java5-jdk 。

                  5. 下載 Android 源代碼

                    5.1 安裝 repo 腳本

          首先安裝 repo 。在 root 目錄下新建一個 bin 目錄。在終端中執行:

          cd ~

          mkdir bin

          然后,向 PATH 中添加 bin 路徑:

          export PATH=$PATH:~/bin

          然后執行下面兩行指令,下載 repo 腳本并修改可執行屬性:

          curl https://android.git.kernel.org/repo >~/bin/repo

          chmod a+x ~/bin/repo

                    5.2 初始化 repo

          首先建立一個目錄用來存放 Android 源代碼:

          mkdir mydroid

          cd mydroid

          然后用最新的列表執行初始化。這里我們下載android 2.1-r1,因此加了參數 –b android-2.1_r2:

          repo init -u git://android.git.kernel.org/platform/manifest.git –b android-2.1_r2

          這中間會問到你的名字和 Email 。如果你打算上傳代碼, Email 須是一個 Google 賬戶。

          repo 初始化成功后會看到類似于下面的提示:

          repo initialized in /root/mydroid

          最后執行 repo sync 開始同步代碼。過程比較漫長,下載速度取決于你的網速,中間有可能遇到斷線,重新執行 repo sync 即可斷點續傳。

                 6. 編譯 Android 源代碼

                   6.1 編譯生成鏡像

          切換到 android 源碼根目錄下,執行 make 即可。首次編譯非常耗時,取決于機器配置,大約需要 3 小時。完成后鏡像生成在 /root/mydroid/out/target/product/generic 下。

                   6.2 編譯、配置 Android SDK

          make 編譯完成后,執行 make sdk 命令,生成對應于該版本源代碼的 sdk 。

          Android 官方的 SDK 和我們自己編譯 Android 源碼時使用 make sdk 編譯出的 SDK 有區別,模擬器版本不同,加載的默認鏡像也不同(一個是官方的,一個是自己編譯的)。下面將展示如何能夠自由切換 SDK 版本。

          首先是自己編譯的 SDK 版本,實際位置是 /root/mydroid/out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86 。

          因為它比較常用,我們給它高優先級:

          update-alternatives --install /usr/bin/AndroidSDK AndroidSDK /root/mydroid/out/host/linux-x86/sdk/android-sdk_eng.root_linux-x86 255

          事先下載的官方 SDK 位置是 /root/android-sdk-linux_86 ,執行:

          update-alternatives --install /usr/bin/AndroidSDK AndroidSDK /root/android-sdk-linux_86 0

          然后使用 update-alternatives --display AndroidSDK 查看當前配置情況:

          如果要切換配置,使用 update-alternatives --config AndroidSDK

          配置 AndroidSDK 環境變量。終端中執行 gedit ~/.bashrc

          在文件最后添加下面三行:

          # set android environment

          export ANDROID_SDK_HOME=/usr/bin/ AndroidSDK

          export PATH=$ANDROID_SDK_HOME/tools:$PATH

          保存文件。在終端中執行 source ~/.bashrc

                 7. 在模擬器中運行編譯的鏡像

          打開終端,執行 android 腳本:

          android

          出現下圖所示窗口:

          選擇左邊第一項 Virtual Devices ,然后在右邊選擇 New ,新建一個 AVD 。

          Name : AVD 的名稱,隨便取,但只能包含字母和數字以及點、下劃線和連字符,這里取名 test 。

          Traget :目標 SDK 版本,這里選自己編譯的 2.1-r1 版 Android SDK 。

          SD Card : SD 卡。暫且不填,待需要時再設置。

          Skin :皮膚(模擬器屏幕分辨率)。

          Hardware :使用默認即可

          然后點 Create AVD ,就創建好了一個 AVD 。點擊 Start 即可啟動模擬器,其運行的是自己編譯的鏡像。

          posted @ 2011-08-19 15:30 馬航 閱讀(266) | 評論 (0)編輯 收藏

          Android 2.1

            |-- Makefile

            |-- bionic (bionic C庫)

            |-- bootable (啟動引導相關代碼)

            |-- build (存放系統編譯規則及generic等基礎開發包配置)

            |-- cts (Android兼容性測試套件標準)

            |-- dalvik (dalvik JAVA虛擬機)

            |-- development (應用程序開發相關)

            |-- external (android使用的一些開源的模組)

            |-- frameworks (核心框架——java及C++語言)

            |-- hardware (主要保護硬解適配層HAL代碼)

            |-- out (編譯完成后的代碼輸出與此目錄)

            |-- packages (應用程序包)

            |-- prebuilt (x86和arm架構下預編譯的一些資源)

            |-- sdk (sdk及模擬器)

            |-- system (文件系統庫、應用及組件——C語言)

            `-- vendor (廠商定制代碼)

            bionic 目錄按照二級展開 tree -d -L 2

            |-- libc (C庫)

            | |-- arch-arm (ARM架構,包含系統調用匯編實現)

            | |-- arch-x86 (x86架構,包含系統調用匯編實現)

            | |-- bionic (由C實現的功能,架構無關)

            | |-- docs (文檔)

            | |-- include (頭文件)

            | |-- inet (?inet相關,具體作用不明)

            | |-- kernel (Linux內核中的一些頭文件)

            | |-- netbsd (?nesbsd系統相關,具體作用不明)

            | |-- private (?一些私有的頭文件)

            | |-- stdio (stdio實現)

            | |-- stdlib (stdlib實現)

            | |-- string (string函數實現)

            | |-- tools (幾個工具)

            | |-- tzcode (時區相關代碼)

            | |-- unistd (unistd實現)

            | `-- zoneinfo (時區信息)

            |-- libdl (libdl實現,dl是動態鏈接,提供訪問動態鏈接庫的功能)

            |-- libm (libm數學庫的實現,)

            | |-- alpha (apaha架構)

            | |-- amd64 (amd64架構)

            | |-- arm (arm架構)

            | |-- bsdsrc (?bsd的源碼)

            | |-- i386 (i386架構)

            | |-- i387 (i387架構?)

            | |-- ia64 (ia64架構)

            | |-- include (頭文件)

            | |-- man (數學函數,后綴名為.3,一些為freeBSD的庫文件)

          | |-- powerpc (powerpc架構)

            | |-- sparc64 (sparc64架構)

            | `-- src (源代碼)

            |-- libstdc++ (libstdc++ C++實現庫)

            | |-- include (頭文件)

            | `-- src (源碼)

            |-- libthread_db (多線程程序的調試器庫)

            | `-- include (頭文件)

            `-- linker (動態鏈接器)

            `-- arch (支持arm和x86兩種架構)

            hardware 目錄 (部分廠家開源的硬解適配層HAL代碼)

            |-- broadcom (博通公司)

            | `-- wlan (無線網卡)

            |-- libhardware (硬件庫)

            | |-- include (頭文件)

            | `-- modules (Default (and possibly architecture dependents) HAL modules)

            | |-- gralloc (gralloc顯示相關)

            | `-- overlay (Skeleton for the "overlay" HAL module.)

            |-- libhardware_legacy (舊的硬件庫)

            | |-- flashlight (背光)

            | |-- gps (GPS)

            | |-- include (頭文件)

            | |-- mount (舊的掛載器)

            | |-- power (電源)

            | |-- qemu (模擬器)

            | |-- qemu_tracing (模擬器跟蹤)

            | |-- tests (測試)

            | |-- uevent (uevent)

            | |-- vibrator (震動)

            | `-- wifi (無線)

            |-- msm7k (高通7k處理器開源抽象層)

            | |-- boot (啟動)

            | |-- libaudio (聲音庫)

            | |-- libaudio-qsd8k (qsd8k的聲音相關庫)

            | |-- libcamera (攝像頭庫)

            | |-- libcopybit (copybit庫)

            | |-- libgralloc (gralloc庫)

            | |-- libgralloc-qsd8k (qsd8k的gralloc庫)

            | |-- liblights (背光庫)

            | `-- librpc (RPC庫)

            |-- ril (無線電抽象層)

            | |-- include (頭文件)

            | |-- libril (庫)

            | |-- reference-cdma-sms (cdma短信參考)

            | |-- reference-ril (ril參考)

            | `-- rild (ril后臺服務程序)

            `-- ti (ti公司開源HAL)

            |-- omap3 (omap3處理器)

            | |-- dspbridge (DSP橋)

            | |-- libopencorehw (opencore硬件庫)

          | |-- liboverlay (overlay硬件庫)

            | |-- libstagefrighthw (stagefright硬件庫)

            | `-- omx (omx組件)

            `-- wlan (無線網卡)

            prebuilt 目錄 (x86和arm架構下預編譯的一些資源)

            .

            |-- android-arm (arm-android相關)

            | |-- gdbserver (gdb調試器)

            | `-- kernel (模擬的arm內核)

            |-- android-x86 (x86-android相關)

            | `-- kernel (空的)

            |-- common (通用編譯好的代碼,應該是java的)

            |-- darwin-x86 (drawin x86平臺)

            | `-- toolchain (工具鏈)

            | |-- arm-eabi-4.2.1

            | |-- arm-eabi-4.3.1

            | `-- arm-eabi-4.4.0

            |-- darwin-x86_64 (drawin x86 64bit平臺)

            |-- linux-x86 (linux x86平臺)

            | `-- toolchain (工具鏈,我們應該主要用這個)

            | |-- arm-eabi-4.2.1

            | |-- arm-eabi-4.3.1

            | |-- arm-eabi-4.4.0

            | `-- i686-unknown-linux-gnu-4.2.1 (x86版編譯器)

            |-- linux-x86_64 (linux x86 64bit平臺)

            |-- windows (windows平臺)

            `-- windows-x86_64 (64bit windows平臺)

            system 目錄 (底層文件系統庫、應用及組件——C語言)

            .

            |-- Bluetooth (藍牙相關)

            |-- core (系統核心工具盒接口)

            | |-- adb (adb調試工具)

            | |-- cpio (cpio工具,創建img)

            | |-- debuggerd (調試工具)

            | |-- fastboot (快速啟動相關)

            | |-- include (系統接口頭文件)

            | |-- init (init程序源代碼)

            | |-- libacc (輕量級C編譯器)

            | |-- libctest (libc測試相關)

            | |-- libcutils (libc工具)

            | |-- liblog (log庫)

            | |-- libmincrypt (加密庫)

            | |-- libnetutils (網絡工具庫)

            | |-- libpixelflinger (圖形處理庫)

            | |-- libsysutils (系統工具庫)

            | |-- libzipfile (zip庫)

            | |-- logcat (查看log工具)

            | |-- logwrapper (log封裝工具)

            | |-- mkbootimg (制作啟動boot.img的工具盒腳本)

           | |-- netcfg (網絡配置netcfg源碼)

            | |-- nexus (google最新手機的代碼)

            | |-- rootdir (rootfs,包含一些etc下的腳本和配置)

            | |-- sh (shell代碼)

            | |-- toolbox (toolbox,類似busybox的工具集)

            | `-- vold (SD卡管理器)

            |-- extras (額外工具)

            | |-- latencytop (a tool for software developers ,identifying system latency happen)

            | |-- libpagemap (pagemap庫)

            | |-- librank (Java Library Ranking System庫)

            | |-- procmem (pagemap相關)

            | |-- procrank (Java Library Ranking System相關)

            | |-- showmap (showmap工具)

            | |-- showslab (showslab工具)

            | |-- sound (聲音相關)

            | |-- su (su命令源碼)

            | |-- tests (一些測試工具)

            | `-- timeinfo (時區相關)

            `-- wlan (無線相關)

            `-- ti (ti網卡相關工具及庫)

          posted @ 2011-08-19 15:22 馬航 閱讀(129) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 神木县| 乐清市| 高尔夫| 宁远县| 汝州市| 北流市| 丽江市| 广南县| 理塘县| 贵州省| 台山市| 阿拉尔市| 虎林市| 光泽县| 济南市| 太仓市| 历史| 波密县| 宁夏| 嘉善县| 奉贤区| 军事| 溆浦县| 达拉特旗| 黔东| 定边县| 池州市| 科尔| 宜兴市| 德江县| 林口县| 泰安市| 眉山市| 积石山| 曲周县| 松阳县| 黎川县| 阳朔县| 双峰县| 九江市| 邳州市|