2010年12月9日
#
http://viralpatel.net/blogs/2009/12/tutorial-create-struts-2-application-eclipse-example.html problem:
HTTP Status 500
java.lang.NullPointerException
org.apache.struts2.impl.StrutsActionProxy.getErrorMessage(StrutsActionProxy.java:69)
com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
resolve problem:
1. struts.xml should under src
2. in struts.xml:
<action name="login" method="
excute" class="net.viralpatel.struts2.LoginAction">
24.Sep.2009 | by Gusac | Filed in: Articles, Tutorials
With the lack of Graphical Interface on Windows 2008 Core server there comes a need of performing a lot of task through command line. One of which is checking file properties like file version, path, product verision etc. Luckily we have a command that makes this task simple. On a side note, We can also run the same command on other operating systems like Windows Xp, 2003, vista.
Here is the command:
wmic datafile where name='c:\\windows\\system32\\notepad.exe'
Click here to view the enlarged screenshot
Notice that we have used two backslashes \\ in the file path. Also, notice that the path is enclosed in the single quotes.
The output will be confusing to read in command prompt window. To read and understand it better, we can take the output in text format and read it in notepad.
While doing so, please do NOT wrap the text.
wmic datafile where name='c:\\windows\\system32\\notepad.exe' > out.txt

Click here to view the enlarged screenshot
The output will reveal the file properties like Hidden, Path, Drive, Version Caption, Access rights etc.
To get one particular property of a file we need to modify the command a little bit. We need to use the GET Alias injunction to the command mentioned above. Let's say we want to check the version for the file notepad.exe. The command that is used for this is:
wmic datafile where name='c:\\windows\\system32\\notepad.exe' get version
Similarily, there is a list of properties that can be fetched through this command line. They are:
Access Rights
Caption
Class Name
Compressed
Compression Method
Computer System Class Name
Computer System Name
Creation Date
Current File Open Count
Description
Drive
Eight Dot Three File Name
Encrypted
Encryption Method
File Extension
File Name
File System Class Name
File System Name
File Type
Hidden
Install Date
Last Accessed
Last Modified
Manufacturer
Name
Path
Readable
Should Be Archived
Size
Status
System File
Version
Writeable
from
http://www.iis.net/ConfigReference/system.webServer/security/authentication/windowsAuthentication
The <windowsAuthentication>
element defines configuration settings for the Internet Information Services (IIS) 7 Windows authentication module. You can use Windows authentication when your IIS 7 server runs on a corporate network that is using Microsoft Active Directory service domain identities or other Windows accounts to identify users. Because of this, you can use Windows authentication whether or not your server is a member of an Active Directory domain.
Windows authentication (formerly named NTLM, and also referred to as Windows NT Challenge/Response authentication) is a secure form of authentication because the user name and password are hashed before being sent across the network. When you enable Windows authentication, the client browser sends a strongly hashed version of the password in a cryptographic exchange with your Web server.
Windows authentication supports two authentication protocols, Kerberos and NTLM, which are defined in the <providers>
element. When you install and enable Windows authentication on IIS 7, the default protocol is Kerberos. The <windowsAuthentication>
element can also contain a useKernelMode attribute that configures whether to use the kernel mode authentication feature that is new to Windows Server 2008.
Windows authentication is best suited for an intranet environment for the following reasons:
- Client computers and Web servers are in the same domain.
- Administrators can make sure that every client browser is Internet Explorer 2.0 or later.
- HTTP proxy connections, which are not supported by NTLM, are not required.
- Kerberos version 5 requires a connection to Active Directory, which is not feasible in an Internet environment.
New in IIS 7.5
The <extendedProtection>
element was introduced in IIS 7.5, which allows you to configure the settings for the new extended protection features that have been integrated into Windows authentication.
Version |
Notes |
IIS 7.5 |
The <extendedProtection> element was added in IIS 7.5. |
IIS 7.0 |
The <windowsAuthentication> element was introduced in IIS 7.0. |
IIS 6.0 |
The <windowsAuthentication> element replaces portions of the IIS 6.0 AuthType and AuthFlags metabase properties. |
The default installation of IIS 7 does not include the Windows authentication role service. To use Windows authentication on IIS, you must install the role service, disable Anonymous authentication for your Web site or application, and then enable Windows authentication for the site or application.
Note: After you install the role service, IIS 7 commits the following configuration settings to the ApplicationHost.config file.
<windowsAuthentication enabled="false" />
Windows Server 2008 or Windows Server 2008 R2
- On the taskbar, click Start, point to Administrative Tools, and then click Server Manager.
- In the Server Manager hierarchy pane, expand Roles, and then click Web Server (IIS).
- In the Web Server (IIS) pane, scroll to the Role Services section, and then click Add Role Services.
- On the Select Role Services page of the Add Role Services Wizard, select Windows Authentication, and then click Next.
- On the Confirm Installation Selections page, click Install.
- On the Results page, click Close.
Windows Vista or Windows 7
- On the taskbar, click Start, and then click Control Panel.
- In Control Panel, click Programs and Features, and then click Turn Windows Features on or off.
- Expand Internet Information Services, then World Wide Web Services, then Security.
- Select Windows Authentication, and then click OK.
How to enable Windows authentication for a Web site, Web application, or Web service
- Open Internet Information Services (IIS) Manager:
- If you are using Windows Server 2008 or Windows Server 2008 R2:
- On the taskbar, click Start, point to Administrative Tools, and then click Internet Information Services (IIS) Manager.
- If you are using Windows Vista or Windows 7:
- On the taskbar, click Start, and then click Control Panel.
- Double-click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
- In the Connections pane, expand the server name, expand Sites, and then the site, application, or Web service for which you want to enable Windows authentication.
- Scroll to the Security section in the Home pane, and then double-click Authentication.
- In the Authentication pane, select Windows Authentication, and then click Enable in the Actions pane.
How to enable Extended Protection for Windows authentication
- Open Internet Information Services (IIS) Manager:
- If you are using Windows Server 2008 or Windows Server 2008 R2:
- On the taskbar, click Start, point to Administrative Tools, and then click Internet Information Services (IIS) Manager.
- If you are using Windows Vista or Windows 7:
- On the taskbar, click Start, and then click Control Panel.
- Double-click Administrative Tools, and then double-click Internet Information Services (IIS) Manager.
- In the Connections pane, expand the server name, expand Sites, and then the site, application, or Web service for which you want to enable Extended Protection for Windows authentication.
- Scroll to the Security section in the Home pane, and then double-click Authentication.
- In the Authentication pane, select Windows Authentication.
- Click Enable in the Actions pane.
- Click Advanced Settings in the Actions pane.
- When the Advanced Settings dialog box appears, select one of the following options in the Extended Protection drop-down menu:
- Select Accept if you want to enable extended protection while providing down-level support for clients that do not support extended protection.
- Select Required if you want to enable extended protection without providing down-level support.
- Click OK to close the Advanced Settings dialog box.
The <windowsAuthentication>
element is configurable at the site, application, or virtual directory level in the ApplicationHost.config file.
Attributes
Attribute |
Description |
authPersistNonNTLM |
Optional Boolean attribute.
Specifies whether IIS automatically reauthenticates every non-NTLM (for example, Kerberos) request, even those on the same connection. False enables multiple authentications for the same connections.
Note: A setting of true means that the client will be authenticated only once on the same connection. IIS will cache a token or ticket on the server for a TCP session that stays established.
The default is false . |
authPersistSingleRequest |
Optional Boolean attribute.
Setting this flag to true specifies that authentication persists only for a single request on a connection. IIS resets the authentication at the end of each request, and forces reauthentication on the next request of the session.
The default value is false . |
enabled |
Required Boolean attribute.
Specifies whether Windows authentication is enabled.
The default value is false . |
useKernelMode |
Optional Boolean attribute.
Specifies whether Windows authentication is done in kernel mode. True specifies that Windows authentication uses kernel mode.
Kernel-mode authentication may improve authentication performance and prevent authentication problems with application pools that are configured to use a custom identity.
As a best practice, do not disable this setting if you use Kerberos authentication and have a custom identity on the application pool.
The default is true . |
Child Elements
Element |
Description |
extendedProtection |
Optional element.
Specifies extended protection options for Windows authentication.
Note: This element was added in IIS 7.5. |
providers |
Optional element.
Specifies security support providers used for Windows authentication. |
Configuration Sample
The following default <windowsAuthentication>
element is configured at the root ApplicationHost.config file in IIS 7.0, and disables Windows authentication by default. It also defines the two Windows authentication providers for IIS 7.0.
<windowsAuthentication enabled="false">
<providers>
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
The following example enables Windows authentication and disables Anonymous authentication for a Web site named Contoso.
<location path="Contoso">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" />
</authentication>
</security>
</system.webServer>
</location>
The following examples disable Anonymous authentication for a site named Contoso, then enable Windows authentication for the site.
AppCmd.exe
appcmd.exe set config "Contoso" -section:system.webServer/security/authentication/anonymousAuthentication /enabled:"False" /commit:apphost
appcmd.exe set config "Contoso" -section:system.webServer/security/authentication/windowsAuthentication /enabled:"True" /commit:apphost
Note: You must be sure to set the commit parameter to apphost
when you use AppCmd.exe to configure these settings. This commits the configuration settings to the appropriate location section in the ApplicationHost.config file.
C#
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample {
private static void Main() {
using(ServerManager serverManager = new ServerManager()) {
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection anonymousAuthenticationSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", "Contoso");
anonymousAuthenticationSection["enabled"] = false;
ConfigurationSection windowsAuthenticationSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", "Contoso");
windowsAuthenticationSection["enabled"] = true;
serverManager.CommitChanges();
}
}
}
VB.NET
Imports System
Imports System.Text
Imports Microsoft.Web.Administration
Module Sample
Sub Main()
Dim serverManager As ServerManager = New ServerManager
Dim config As Configuration = serverManager.GetApplicationHostConfiguration
Dim anonymousAuthenticationSection As ConfigurationSection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", "Contoso")
anonymousAuthenticationSection("enabled") = False
Dim windowsAuthenticationSection As ConfigurationSection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", "Contoso")
windowsAuthenticationSection("enabled") = True
serverManager.CommitChanges()
End Sub
End Module
JavaScript
var adminManager = new ActiveXObject('Microsoft.ApplicationHost.WritableAdminManager');
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST";
var anonymousAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/anonymousAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso");
anonymousAuthenticationSection.Properties.Item("enabled").Value = false;
var windowsAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/windowsAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso");
windowsAuthenticationSection.Properties.Item("enabled").Value = true;
adminManager.CommitChanges();
VBScript
Set adminManager = CreateObject("Microsoft.ApplicationHost.WritableAdminManager")
adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST"
Set anonymousAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/anonymousAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso")
anonymousAuthenticationSection.Properties.Item("enabled").Value = False
Set windowsAuthenticationSection = adminManager.GetAdminSection("system.webServer/security/authentication/windowsAuthentication", "MACHINE/WEBROOT/APPHOST/Contoso")
windowsAuthenticationSection.Properties.Item("enabled").Value = True
adminManager.CommitChanges()
how to check window version
run: Winver
Here's How:
-
Open the System Information
Open the Start menu, and click on Programs -> Accessories -> System Tools -> System Information
-
Look in the System Summary
The System Information tool will display detailed information about your Windows operating system. Once opened it will show the "System Summary" – it’s an overview of your computer and operating system.
-
Look for the System Type Item
On the right hand side of the window you will see a list of items. Look for the item called "System Type".
The value of this item will tell you whether your computer is 32-bit or 64-bit:
- x86-based PC: It’s a 32-bit computer.
- x64-based PC: It’s a 64-bit computer.
摘要: ContentProvider何時(shí)創(chuàng)建呢?這是一個(gè)值得深思的問題?
據(jù)我這兩天的了解是在你要用到的時(shí)候才會(huì)調(diào)用ContentProvider的onCreate函數(shù)進(jìn)行創(chuàng)建。你就會(huì)什么時(shí)候叫要用到的時(shí)候呢?比如你要查詢或刪除修改數(shù)據(jù)庫(kù)的時(shí)候通過ContentResolver的quire或delete來操縱數(shù)據(jù)時(shí)就會(huì)調(diào)用ContentProvider的onCreate函數(shù),若已經(jīng)創(chuàng)建了數(shù)...
閱讀全文
View是在onTouchEvent(MotionEvent event)里對(duì)用戶的動(dòng)作做了一定的分析,從而通知我們是發(fā)生了點(diǎn)擊還是長(zhǎng)按等事件。
我們需要?jiǎng)?chuàng)建一個(gè)GestureDetector的對(duì)象,傳入listener對(duì)象,view接收到的onTouchEvent中將event傳給GestureDetector進(jìn)行分析,listener會(huì)回調(diào)給我們相應(yīng)的動(dòng)作。其中GestureDetector.SimpleOnGestureListener(Framework幫我們簡(jiǎn)化了)是實(shí)現(xiàn)了上面提到的OnGestureListener和OnDoubleTapListener兩個(gè)接口的類,我們只需要繼承它并重寫其中我們關(guān)心的回調(diào)即可。
,那么,這個(gè)類如何使用呢?以下是使用該類的一個(gè)范例:
private GestureDetector mGestureDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGestureDetector = new GestureDetector(this, new MyGestureListener());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
/* 有關(guān)上面的 onTouchEvent方法,我們可以直接判斷MotionEvent的類型,
對(duì)于手勢(shì)移動(dòng)僅僅捕獲ACTION_MOVE即可,
我們通過參數(shù)MotionEvent e1, MotionEvent e2,float distanceX, float distanceY可以獲取操作變化。
比如 distanceX > 0 向右邊移動(dòng),distanceX < 0 則向左邊,distanceY > 0 向上滾動(dòng), distanceY < 0 向下滾動(dòng)。
*/
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onSingleTapUp(MotionEvent ev) {
Log.d("onSingleTapUp",ev.toString());
return true;
}
@Override
public void onShowPress(MotionEvent ev) {
Log.d("onShowPress",ev.toString());
}
@Override
public void onLongPress(MotionEvent ev) {
Log.d("onLongPress",ev.toString());
}
}
更多的回調(diào)消息,方便的對(duì)用戶的動(dòng)作進(jìn)行響應(yīng)
public interface OnGestureListener {
// Touch down時(shí)觸發(fā), e為down時(shí)的MotionEvent
boolean onDown(MotionEvent e);
// 在Touch down之后一定時(shí)間(115ms)觸發(fā),e為down時(shí)的MotionEvent
void onShowPress(MotionEvent e);
// Touch up時(shí)觸發(fā),e為up時(shí)的MotionEvent
boolean onSingleTapUp(MotionEvent e);
// 滑動(dòng)時(shí)觸發(fā),e1為down時(shí)的MotionEvent,e2為move時(shí)的MotionEvent
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
// 在Touch down之后一定時(shí)間(500ms)觸發(fā),e為down時(shí)的MotionEvent
void onLongPress(MotionEvent e);
// 滑動(dòng)一段距離,up時(shí)觸發(fā),e1為down時(shí)的MotionEvent,e2為up時(shí)的MotionEvent
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}
public interface OnDoubleTapListener {
// 完成一次單擊,并確定沒有二擊事件后觸發(fā)(300ms),e為down時(shí)的MotionEvent
boolean onSingleTapConfirmed(MotionEvent e);
// 第二次單擊down時(shí)觸發(fā),e為第一次down時(shí)的MotionEvent
boolean onDoubleTap(MotionEvent e);
// 第二次單擊down,move和up時(shí)都觸發(fā),e為不同時(shí)機(jī)下的MotionEvent
boolean onDoubleTapEvent(MotionEvent e);
}
boolean onDoubleTap(MotionEvent e)
解釋:雙擊的第二下Touch down時(shí)觸發(fā)
boolean onDoubleTapEvent(MotionEvent e)
解釋:雙擊的第二下Touch down和up都會(huì)觸發(fā),可用e.getAction()區(qū)分。
boolean onDown(MotionEvent e)
解釋:Touch down時(shí)觸發(fā)
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
解釋:Touch了滑動(dòng)一點(diǎn)距離后,up時(shí)觸發(fā)。
void onLongPress(MotionEvent e)
解釋:Touch了不移動(dòng)一直Touch down時(shí)觸發(fā)
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
解釋:Touch了滑動(dòng)時(shí)觸發(fā)。
void onShowPress(MotionEvent e)
解釋:Touch了還沒有滑動(dòng)時(shí)觸發(fā)
(與onDown,onLongPress比較,onDown只要Touch down一定立刻觸發(fā)。而Touchdown后過一會(huì)沒有滑動(dòng)先觸發(fā)onShowPress再是onLongPress。
所以Touchdown后一直不滑動(dòng),onDown->onShowPress->onLongPress這個(gè)順序觸發(fā)。
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋:上面這兩個(gè)函數(shù)都是在touch down后又沒有滑動(dòng)(onScroll),又沒有長(zhǎng)按(onLongPress),然后Touchup時(shí)觸發(fā)。
點(diǎn)擊一下非??斓模ú换瑒?dòng))Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點(diǎn)擊一下稍微慢點(diǎn)的(不滑動(dòng))Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
protected void onNewIntent (Intent intent)
This is called for activities that set launchMode to "singleTop" in their package, or if a client used theFLAG_ACTIVITY_SINGLE_TOP
flag when calling startActivity(Intent)
. In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
An activity will always be paused before receiving a new intent, so you can count on onResume()
being called after this method.
Note that getIntent()
still returns the original Intent. You can use setIntent(Intent)
to update it to this new Intent.
在IntentActivity中重寫下列方法:onCreate onStart onRestart onResume onPause onStop onDestroy onNewIntent
一、其他應(yīng)用發(fā)Intent,執(zhí)行下列方法:
I/@@@philn(12410): onCreate
I/@@@philn(12410): onStart
I/@@@philn(12410): onResume
發(fā)Intent的方法:
Uri uri = Uri.parse("philn://blog.163.com");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
二、接收Intent聲明:
<activity android:name=".IntentActivity" android:launchMode="singleTask"
android:label="@string/testname">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="philn"/>
</intent-filter>
</activity>
三、如果IntentActivity處于任務(wù)棧的頂端,也就是說之前打開過的Activity,現(xiàn)在處于
I/@@@philn(12410): onPause
I/@@@philn(12410): onStop 狀態(tài)的話
其他應(yīng)用再發(fā)送Intent的話,執(zhí)行順序?yàn)椋?br style="line-height: 22px; " />
I/@@@philn(12410): onNewIntent
I/@@@philn(12410): onRestart
I/@@@philn(12410): onStart
I/@@@philn(12410): onResume
引言:
設(shè)計(jì)模式是經(jīng)驗(yàn)的文檔化。它是對(duì)被用來在特定場(chǎng)景下解決一般設(shè)計(jì)問題的類和相互通信的對(duì)象的描述。更通俗的來說,它是一個(gè)問題/解決方案對(duì)。一旦我們掌握了設(shè)計(jì)模式,就等于擁有了一支強(qiáng)有力的專家隊(duì)伍。它甚至能夠使面向?qū)ο蟮男率掷们叭说慕?jīng)驗(yàn)找出職責(zé)明確的類和對(duì)象,從而獲得優(yōu)雅的解決方案。由于設(shè)計(jì)模式也是重構(gòu)的目標(biāo),如果在設(shè)計(jì)的初期適當(dāng)?shù)匾朐O(shè)計(jì)模式,可以減少重構(gòu)的工作量。
但是,我們也不能陷入模式的陷阱,為了使用模式而去套模式,那樣會(huì)陷入形式主義。我們?cè)谑褂媚J降臅r(shí)候,一定要注意模式的意圖(intent),而不要過多的去關(guān)注模式的實(shí)現(xiàn)細(xì)節(jié),因?yàn)檫@些實(shí)現(xiàn)細(xì)節(jié)在特定情況下,可能會(huì)發(fā)生一些改變。不要頑固地認(rèn)為設(shè)計(jì)模式一書中的類圖或?qū)崿F(xiàn)代碼就代表了模式本身。
下面,我們來討論一下為什么要在分布式、多層系統(tǒng)中使用Observer模式。
多層體系結(jié)構(gòu)(multi-tier architecture):
三層體系結(jié)構(gòu)是多層體系結(jié)構(gòu)中最簡(jiǎn)單的一種,它一般包括:
- 表示層(presentation)-窗口、報(bào)表-
- 業(yè)務(wù)邏輯層(business logic)-管理業(yè)務(wù)過程的任務(wù)和規(guī)則。它又可以細(xì)分為領(lǐng)域?qū)ο髮樱ù眍I(lǐng)域概念)和服務(wù)層(提供數(shù)據(jù)庫(kù)交互、安全性、打印報(bào)表)。
- 存儲(chǔ)層(storage)-持久化存儲(chǔ)機(jī)制。如數(shù)據(jù)庫(kù)服務(wù)器等。
圖一:三層體系結(jié)構(gòu)
而Java 2平臺(tái)企業(yè)版(J2EE)是一種利用Java 2平臺(tái)來簡(jiǎn)化諸多與多級(jí)企業(yè)解決方案的開發(fā)、部署和管理相關(guān)的復(fù)雜問題的體系結(jié)構(gòu)。它是開放的、基于標(biāo)準(zhǔn)的平臺(tái),用以開發(fā)、部署和管理N層結(jié)構(gòu)、面向Web的,以服務(wù)器為中心的企業(yè)級(jí)應(yīng)用。
為了支持領(lǐng)域?qū)ο蟮膹?fù)用,并且使領(lǐng)域?qū)ο蟮慕涌谧兏鶐淼挠绊懽钚』N覀儗㈩I(lǐng)域?qū)樱P停┖捅硎緦樱ㄒ晥D)相分離。
采用模型-視圖模式的意義在于:
- 支持聚合度更高的模型定義,使模型的定義可以集中在領(lǐng)域過程的定義,而不是圖形界面上。
- 允許將模型和用戶界面并行開發(fā)。
- 使用戶界面的需求變化對(duì)領(lǐng)域?qū)铀斐傻挠绊懽钚』?/li>
- 允許建立與一個(gè)現(xiàn)有的領(lǐng)域?qū)訉?duì)象相連接的新視圖,同時(shí)不影響領(lǐng)域?qū)印?/li>
- 允許一個(gè)模型同時(shí)有多個(gè)視圖,例如使用SVG和表格。
- 允許模型層獨(dú)立于用戶界面層執(zhí)行。
而這恰恰與Observer模式的意圖相吻合。因此我們有必要跨層來實(shí)現(xiàn)Observer模式。
其實(shí),在應(yīng)用中更多的是采用MVC框架來架構(gòu)整個(gè)企業(yè)應(yīng)用的。在MVC框架中,Model和View之間存在著依賴關(guān)系,是Observer模式的典型應(yīng)用。當(dāng)然MVC框架還包括其它模式如Composite模式和Strategy模式。在J2EE平臺(tái)中,我們可以把Web Tier(包括Jsp和servelet和JavaBean)看作是表示層,EJB Tier看作是領(lǐng)域?qū)印6鴆ontroller可能跨距Web Tier和 EJB Tier。
在Java類庫(kù)中采用Java.util.Observable類和Java.util.Observer接口來實(shí)現(xiàn)Observer模式,它們?cè)趩蝹€(gè)的Java VM.中運(yùn)行的很好,但如果想在EJB中使用它們就會(huì)有一些問題。這正如我們引言中提到的,模式的具體實(shí)現(xiàn)在特定情況下,可能會(huì)發(fā)生一些改變。
值傳遞還是遠(yuǎn)程引用傳遞?
值傳遞:
在Java RMI中要求所有的參數(shù)和返回類型是JAVA的基本類型或?qū)崿F(xiàn)Java.io.Serilizable的對(duì)象。串行化對(duì)象通過值傳遞(又名拷貝傳遞),而不是引用傳遞,這意味著在某一層中串行化對(duì)象的更并不自動(dòng)影響到其它的對(duì)象。
遠(yuǎn)程引用傳遞:
對(duì)于EJB對(duì)象而言,它由兩個(gè)接口(home接口和remote接口)和一個(gè)類組成。容器會(huì)根據(jù)ejb規(guī)范來生成實(shí)現(xiàn)上面兩個(gè)接口的類(我們分別稱為xxxEJBHome對(duì)象和xxxEjbObject對(duì)象)。在較多的容器的實(shí)現(xiàn)方案中,xxxEJBHome對(duì)象使用了factory模式來創(chuàng)建xxxEjbObject對(duì)象;xxxEjbObject對(duì)象則采用proxy模式,作為xxxBean的代理類。在生成以上兩個(gè)對(duì)象的同時(shí),容器會(huì)從部署文件中讀取關(guān)于安全、事務(wù)、持久性等服務(wù)并在xxxEjbObject對(duì)象和xxxEJBHome對(duì)象中添加以上服務(wù)的代碼。而且xxxEJBHome對(duì)象和xxxEjbObject對(duì)象都是分布式對(duì)象,我們?cè)诖酥挥懻搙xxEjbObject對(duì)象。所謂分布式對(duì)象,從本質(zhì)上來講,分為3個(gè)部分:object server、skeleton、stub。其中object server和skeleton位于服務(wù)器端,而stub位于客戶端。Object server負(fù)責(zé)實(shí)現(xiàn)業(yè)務(wù)邏輯,skeleton負(fù)責(zé)marshal和unmarshal方法簽名。
圖二:分布式對(duì)象
顯然,EJB的客戶(調(diào)用EJB的對(duì)象)可以是任何對(duì)象,包括EJB和一般的Java類甚至是用任何語言寫的corba客戶端。
從EJB的客戶視角來看的話,我們只能看到一個(gè)home接口、一個(gè)remote接口(對(duì)于實(shí)體bean的話,還可以看見一個(gè)主鍵類,而bean類對(duì)客戶是不可見的)。但我們從上面的論述,我們可以知道,對(duì)于remote接口中地方法調(diào)用,實(shí)際上是多態(tài)地調(diào)用XXX_Stub類。即XXX_Stub對(duì)象對(duì)客戶具有可見性(但這種可見性是透明的,即客戶不知道這種可見性的存在)。由于,XXX_Stub對(duì)象和Object Server實(shí)現(xiàn)了相同的接口,并且Object server真正實(shí)現(xiàn)了業(yè)務(wù)邏輯。所以,當(dāng)在客戶端調(diào)用XXX_Stub對(duì)象的方法時(shí)候,XXX_Stub對(duì)象通過socket通信機(jī)制將方法簽名傳給XXX_Skeleton對(duì)象,XXX_Skeleton對(duì)象在去委托Object Server完成業(yè)務(wù)處理邏輯。因此,Object Server本身發(fā)生了改變。我們稱XXX_Stub對(duì)象是Object Server對(duì)象的遠(yuǎn)程引用,并認(rèn)為當(dāng)分布式對(duì)象作為參數(shù)傳遞的時(shí)候,是通過引用傳遞的(會(huì)產(chǎn)生副作用
RMI的定義
Java RMI (Remote Method Invocation 遠(yuǎn)程方法調(diào)用)是用Java在JDK1.1中實(shí)現(xiàn)的,它大大增強(qiáng)了Java開發(fā)分布式應(yīng)用的能力。Java作為一種風(fēng)靡一時(shí)的網(wǎng)絡(luò)開發(fā)語言,其巨大的威力就體現(xiàn)在它強(qiáng)大的開發(fā)分布式網(wǎng)絡(luò)應(yīng)用的能力上,而RMI就是開發(fā)百分之百純Java的網(wǎng)絡(luò)分布式應(yīng)用系統(tǒng)的核心解決方案之一。其實(shí)它可以被看作是RPC的Java版本。但是傳統(tǒng)RPC并不能很好地應(yīng)用于分布式對(duì)象系統(tǒng)。而Java RMI 則支持存儲(chǔ)于不同地址空間的程序級(jí)對(duì)象之間彼此進(jìn)行通信,實(shí)現(xiàn)遠(yuǎn)程對(duì)象之間的無縫遠(yuǎn)程調(diào)用。
RMI目前使用Java遠(yuǎn)程消息交換協(xié)議JRMP(Java Remote Messaging Protocol)進(jìn)行通信。JRMP是專為Java的遠(yuǎn)程對(duì)象制定的協(xié)議。因此,Java RMI具有Java的“Write Once,Run Anywhere”的優(yōu)點(diǎn),是分布式應(yīng)用系統(tǒng)的百分之百純Java解決方案。用Java RMI開發(fā)的應(yīng)用系統(tǒng)可以部署在任何支持JRE(Java Run Environment Java,運(yùn)行環(huán)境)的平臺(tái)上。但由于JRMP是專為Java對(duì)象制定的,因此,RMI對(duì)于用非Java語言開發(fā)的應(yīng)用系統(tǒng)的支持不足。不能與用非Java語言書寫的對(duì)象進(jìn)行通信。
RMI與CORBA的關(guān)系
RMI 和CORBA常被視為相互競(jìng)爭(zhēng)的技術(shù),因?yàn)閮烧叨继峁?duì)遠(yuǎn)程分布式對(duì)象的透明訪問。但這兩種技術(shù)實(shí)際上是相互補(bǔ)充的,一者的長(zhǎng)處正好可以彌補(bǔ)另一者的短處。RMI 和 CORBA 的結(jié)合產(chǎn)生了 RMI-IIOP,RMI-IIOP 是企業(yè)服務(wù)器端 Java 開發(fā)的基礎(chǔ)
1997 年,IBM 和 Sun Microsystems啟動(dòng)了一項(xiàng)旨在促進(jìn) Java 作為企業(yè)開發(fā)技術(shù)的發(fā)展的合作計(jì)劃。兩家公司特別著力于如何將 Java 用作服務(wù)器端語言,生成可以結(jié)合進(jìn)現(xiàn)有體系結(jié)構(gòu)的企業(yè)級(jí)代碼。所需要的就是一種遠(yuǎn)程傳輸技術(shù),它兼有 Java 的 RMI(Remote Method Invocation,遠(yuǎn)程方法調(diào)用)較少的資源占用量和更成熟的 CORBA(Common Object Request Broker Architecture,公共對(duì)象請(qǐng)求代理體系結(jié)構(gòu))技術(shù)的健壯性。出于這一需要,RMI-IIOP問世了,它幫助將 Java 語言推向了目前服務(wù)器端企業(yè)開發(fā)的主流語言的領(lǐng)先地位。
RMI的組成
一個(gè)正常工作的RMI系統(tǒng)由下面幾個(gè)部分組成:
1、遠(yuǎn)程服務(wù)的接口定義
2、遠(yuǎn)程服務(wù)接口的具體實(shí)現(xiàn)
3、樁(Stub)和框架(Skeleton)文件
4、一個(gè)運(yùn)行遠(yuǎn)程服務(wù)的服務(wù)器
5、一個(gè)RMI命名服務(wù),它允許客戶端去發(fā)現(xiàn)這個(gè)遠(yuǎn)程服務(wù)
6、類文件的提供者(一個(gè)HTTP或者FTP服務(wù)器)
7、一個(gè)需要這個(gè)遠(yuǎn)程服務(wù)的客戶端程序
RMI的實(shí)現(xiàn)
下面我們一步一步建立一個(gè)簡(jiǎn)單的RMI系統(tǒng)。首先在你的機(jī)器里建立一個(gè)新的文件夾,以便放置我們創(chuàng)建的文件,為了簡(jiǎn)單起見,我們只使用一個(gè)文件夾存放客戶端和服務(wù)端代碼,并且在同一個(gè)目錄下運(yùn)行服務(wù)端和客戶端。
如果所有的RMI文件都已經(jīng)設(shè)計(jì)好了,那么你需要下面的幾個(gè)步驟去生成你的系統(tǒng):
1、 編寫并且編譯接口的Java代碼
2、 編寫并且編譯接口實(shí)現(xiàn)的Java代碼
3、 從接口實(shí)現(xiàn)類中生成 Stub 和 Skeleton 類文件
4、 編寫遠(yuǎn)程服務(wù)的主運(yùn)行程序
5、 編寫RMI的客戶端程序
6、 安裝并且運(yùn)行RMI系統(tǒng)
1、接口
第一步就是建立和編譯服務(wù)接口的Java代碼。這個(gè)接口定義了所有的提供遠(yuǎn)程服務(wù)的功能,下面是源程序:
1. //Calculator.java
2. //define the interface
3. import java.rmi.Remote;
4.
5. public interface Calculator extends Remote
6. {
7. public long add(long a, long b)
8. throws java.rmi.RemoteException;
9.
10. public long sub(long a, long b)
11. throws java.rmi.RemoteException;
12.
13. public long mul(long a, long b)
14. throws java.rmi.RemoteException;
15.
16. public long div(long a, long b)
17. throws java.rmi.RemoteException;
18. }
注意,這個(gè)接口繼承自Remote,每一個(gè)定義的方法都必須拋出一個(gè)RemoteException異常對(duì)象。
建立這個(gè)文件,把它存放在剛才的目錄下,并且編譯。
>javac Calculator.java
2、接口的具體實(shí)現(xiàn)
下一步,我們就要寫遠(yuǎn)程服務(wù)的具體實(shí)現(xiàn),這是一個(gè)CalculatorImpl類文件:
1. //CalculatorImpl.java
2. //Implementation
3. import java.rmi.server.UnicastRemoteObject;
4.
5. public class CalculatorImpl extends UnicastRemoteObject implements Calculator
6. {
7.
8. // 這個(gè)實(shí)現(xiàn)必須有一個(gè)顯式的構(gòu)造函數(shù),并且要拋出一個(gè)RemoteException異常
9. public CalculatorImpl()
10. throws java.rmi.RemoteException {
11. super();
12. }
13.
14. public long add(long a, long b)
15. throws java.rmi.RemoteException {
16. return a + b;
17. }
18.
19. public long sub(long a, long b)
20. throws java.rmi.RemoteException {
21. return a - b;
22. }
23.
24. public long mul(long a, long b)
25. throws java.rmi.RemoteException {
26. return a * b;
27. }
28.
29. public long div(long a, long b)
30. throws java.rmi.RemoteException {
31. return a / b;
32. }
33. }
同樣的,把這個(gè)文件保存在你的目錄里然后編譯他。
這個(gè)實(shí)現(xiàn)類使用了UnicastRemoteObject去聯(lián)接RMI系統(tǒng)。在我們的例子中,我們是直接的從UnicastRemoteObject 這個(gè)類上繼承的,事實(shí)上并不一定要這樣做,如果一個(gè)類不是從UnicastRmeoteObject上繼承,那必須使用它的exportObject() 方法去聯(lián)接到RMI。
如果一個(gè)類繼承自UnicastRemoteObject,那么它必須提供一個(gè)構(gòu)造函數(shù)并且聲明拋出一個(gè)RemoteException對(duì)象。當(dāng)這個(gè)構(gòu)造函數(shù)調(diào)用了super(),它久激活UnicastRemoteObject中的代碼完成RMI的連接和遠(yuǎn)程對(duì)象的初始化。
3、Stubs 和Skeletons
下一步就是要使用RMI編譯器rmic來生成樁和框架文件,這個(gè)編譯運(yùn)行在遠(yuǎn)程服務(wù)實(shí)現(xiàn)類文件上。
>rmic CalculatorImpl
在你的目錄下運(yùn)行上面的命令,成功執(zhí)行完上面的命令你可以發(fā)現(xiàn)一個(gè)Calculator_stub.class文件,如果你是使用的Java2SDK,那么你還可以發(fā)現(xiàn)Calculator_Skel.class文件。
4、主機(jī)服務(wù)器
遠(yuǎn)程RMI服務(wù)必須是在一個(gè)服務(wù)器中運(yùn)行的。CalculatorServer類是一個(gè)非常簡(jiǎn)單的服務(wù)器。
1. //CalculatorServer.java
2. import java.rmi.Naming;
3.
4. public class CalculatorServer {
5.
6. public CalculatorServer() {
7. try {
8. Calculator c = new CalculatorImpl();
9. Naming.rebind("rmi://localhost:1099/CalculatorService", c);
10. } catch (Exception e) {
11. System.out.println("Trouble: " + e);
12. }
13. }
14.
15. public static void main(String args[]) {
16. new CalculatorServer();
17. }
18. }
建立這個(gè)服務(wù)器程序,然后保存到你的目錄下,并且編譯它。
5、客戶端
客戶端源代碼如下:
//CalculatorClient.java
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
public class CalculatorClient {
public static void main(String[] args) {
try {
Calculator c = (Calculator)
Naming.lookup(
"rmi://localhost
/CalculatorService");
System.out.println( c.sub(4, 3) );
System.out.println( c.add(4, 5) );
System.out.println( c.mul(3, 6) );
System.out.println( c.div(9, 3) );
}
catch (MalformedURLException murle) {
System.out.println();
System.out.println(
"MalformedURLException");
System.out.println(murle);
}
catch (RemoteException re) {
System.out.println();
System.out.println(
"RemoteException");
System.out.println(re);
}
catch (NotBoundException nbe) {
System.out.println();
System.out.println(
"NotBoundException");
System.out.println(nbe);
}
catch (
java.lang.ArithmeticException
ae) {
System.out.println();
System.out.println(
"java.lang.ArithmeticException");
System.out.println(ae);
}
}
}
保存這個(gè)客戶端程序到你的目錄下(注意這個(gè)目錄是一開始建立那個(gè),所有的我們的文件都在那個(gè)目錄下),并且編譯他。
6、運(yùn)行RMI系統(tǒng)
現(xiàn)在我們建立了所有運(yùn)行這個(gè)簡(jiǎn)單RMI系統(tǒng)所需的文件,現(xiàn)在我們終于可以運(yùn)行這個(gè)RMI系統(tǒng)啦!來享受吧。
我們是在命令控制臺(tái)下運(yùn)行這個(gè)系統(tǒng)的,你必須開啟三個(gè)控制臺(tái)窗口,一個(gè)運(yùn)行服務(wù)器,一個(gè)運(yùn)行客戶端,還有一個(gè)運(yùn)行RMIRegistry。
首先運(yùn)行注冊(cè)程序RMIRegistry,你必須在包含你剛寫的類的那么目錄下運(yùn)行這個(gè)注冊(cè)程序。
>rmiregistry
好,這個(gè)命令成功的話,注冊(cè)程序已經(jīng)開始運(yùn)行了,不要管他,現(xiàn)在切換到另外一個(gè)控制臺(tái),在第二個(gè)控制臺(tái)里,我們運(yùn)行服務(wù)器CalculatorService,因?yàn)镽MI的安全機(jī)制將在服務(wù)端發(fā)生作用,所以你必須增加一條安全策略。以下是對(duì)應(yīng)安全策略的例子
grant {
permission java.security.AllPermission "", "";
};
注意:這是一條最簡(jiǎn)單的安全策略,它允許任何人做任何事,對(duì)于你的更加關(guān)鍵性的應(yīng)用,你必須指定更加詳細(xì)安全策略。
現(xiàn)在為了運(yùn)行服務(wù)端,你需要除客戶類(CalculatorClient.class)之外的所有的類文件。確認(rèn)安全策略在policy.txt文件之后,使用如下命令來運(yùn)行服務(wù)器。
> java -Djava.security.policy=policy.txt CalculatorServer
這個(gè)服務(wù)器就開始工作了,把接口的實(shí)現(xiàn)加載到內(nèi)存等待客戶端的聯(lián)接。好現(xiàn)在切換到第三個(gè)控制臺(tái),啟動(dòng)我們的客戶端。
為了在其他的機(jī)器運(yùn)行客戶端程序你需要一個(gè)遠(yuǎn)程接口(Calculator.class) 和一個(gè)stub(CalculatorImpl_Stub.class)。 使用如下命令運(yùn)行客戶端
> java -Djava.security.policy=policy.txt CalculatorClient
如果所有的這些都成功運(yùn)行,你應(yīng)該看到下面的輸出:
1
9
18
3
如果你看到了上面的輸出,恭喜你,你成功了,你已經(jīng)成功的創(chuàng)建了一個(gè)RMI系統(tǒng),并且使他正確工作了。即使你運(yùn)行在同一個(gè)計(jì)算機(jī)上,RMI還是使用了你的網(wǎng)絡(luò)堆棧和TCP/IP去進(jìn)行通訊,并且是運(yùn)行在三個(gè)不同的Java虛擬機(jī)上。這已經(jīng)是一個(gè)完整的RMI系統(tǒng)。
摘要: java語言里包含了許多對(duì)設(shè)計(jì)模式的直接支持,如command模式,agent模式,observer模式等。雖然java提供的對(duì)這些模式的支持很簡(jiǎn)單,不能滿足比較復(fù)雜的應(yīng)用。但在簡(jiǎn)單的場(chǎng)景下,使用這些類往往能夠得到立桿見影的效果。所以,如果沒有什么特殊需求,還是最好利用java的這些類。
Observ...
閱讀全文
接口:空心圓+直線(唐老鴨類實(shí)現(xiàn)了‘講人話’);
依賴:虛線+箭頭(動(dòng)物和空氣的關(guān)系);
關(guān)聯(lián):實(shí)線+箭頭(企鵝需要知道氣候才遷移);
聚合:空心四邊形+實(shí)線+箭頭(雁群和大雁的關(guān)系);
合成/組合:實(shí)心四邊形+實(shí)線+箭頭(鳥和翅膀的關(guān)系);
泛化/繼承:空心三角形+實(shí)線(動(dòng)物和鳥的繼承關(guān)系);
實(shí)現(xiàn):空心三角形+虛線(實(shí)現(xiàn)大雁飛翔的接口);
UML類圖
-
-
1. 首先看“動(dòng)物”矩形框,它代表一個(gè)類。該類圖分為三層,第一層顯示類的名稱,如果是抽象類就要用斜體顯示。第二層是類的特性,通常就是字段和屬性。第三層是類的操作,通常是方法和行為。
-
注意前面的符號(hào),‘+’表示public, ‘—’ 表示private, ‘#’表示protected.
-
2. “飛翔”矩形框表示一個(gè)接口圖,它與類圖的區(qū)別主要是頂端有《interface》顯示,第一行是接口名稱,第二行是接口方法。接口還有另一種表示方法,俗稱棒棒糖表示法,就是唐老鴨類實(shí)現(xiàn)了“講人話”的接口。
-
-
interface IFly interface Ilanguage
{ {
void Fly(); void Speak();
} }
-
3. 動(dòng)物,鳥,鴨,唐老鴨他們之間都是繼承的關(guān)系,繼承關(guān)系用空心三角形+實(shí)現(xiàn)來表示。
-
-
4.“大雁”實(shí)現(xiàn)了“飛翔”接口。實(shí)現(xiàn)接口用空心三角形+虛線來表示。(注:下面的圖中應(yīng)為空心三角形)
-
-
class Bird:Animal class WideGoose:IFly
{ {
//繼承動(dòng)物類 //實(shí)現(xiàn)飛翔接口
} }
-
5. 企鵝與氣候有很大的關(guān)系,企鵝需要“知道”氣候的變化,需要“了解”氣候規(guī)律。當(dāng)一個(gè)類“知道”另一個(gè)類時(shí),可以用關(guān)聯(lián)(association)關(guān)系。關(guān)聯(lián)關(guān)系用實(shí)線箭頭來表示。
-
-
-
class Penguin :Bird
{
private Climate climate;//在企鵝Penguin中,引用到氣候Climate對(duì)象
}
-
6. “大雁”和“雁群”這兩個(gè)類。大雁是群居動(dòng)物,每只大雁都屬于一個(gè)雁群,一個(gè)雁群可以有多只大雁。所以它們之間就滿足聚合(Aggregation)關(guān)系。聚合表示一種弱的“擁有”關(guān)系,體現(xiàn)的是A對(duì)象可以包含B對(duì)象,但B對(duì)象不是A對(duì)象的一部分。聚合關(guān)系用空心的菱形+ 實(shí)線箭頭表示。
-
-
-
class WideGooseAggregate
{
private WideGoose[] arrayWideGoose;
//在雁群WideGooseAggregate類中,有大雁數(shù)組對(duì)象arrayWideGoose
}
-
7. “鳥”和“翅膀”這兩個(gè)類。鳥和翅膀似整體和部分的關(guān)系,并且翅膀和鳥的生命周期是相同的,在這里鳥和其翅膀就是合成關(guān)系。合成(composition)是一種強(qiáng)的“擁有”關(guān)系,體現(xiàn)了嚴(yán)格的部分和整體的關(guān)系,部分和整體的生命周期一樣。合成關(guān)系用實(shí)心的的菱形+實(shí)線箭頭來表示。另外,合成關(guān)系的連線兩端還有一個(gè)數(shù)字“1”和數(shù)字“2”,,這被稱為基數(shù)。表明這一端的類可以有幾個(gè)實(shí)例,很顯然,一個(gè)鳥應(yīng)該有兩支翅膀。如果一個(gè)類可能有無數(shù)個(gè)實(shí)例,則就用“n”來表示。關(guān)聯(lián)關(guān)系,聚合關(guān)系也可以有基數(shù)的。
-
class Bird
{
private Wing wing;
public Bird()
{
wing=new Wing();
//在鳥Bird類中,初始化時(shí),實(shí)例化翅膀Wing,它們之間同時(shí)生成
}
}
-
8. “動(dòng)物”、“氧氣”與“水”之間。動(dòng)物有幾大特征,比如有新陳代謝,能繁殖。而動(dòng)物要有生命,需要氧氣,水以及食物等。也就是說動(dòng)物依賴于氧氣和水。它們之間是依賴關(guān)系(Dependency),用虛線箭頭來表示。
-
-
-
-
abstract class Animal
{
public bolism(Oxygen oxygen,Water water)
{
}
}
在manifest文件里->activity 添加
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*">
</intent-filter>
這樣就把當(dāng)前程序注冊(cè)為 可以打開/查看所有類型的文件. 或者要查看jpeg, mimeType要改為: image/jpeg
當(dāng)在文件管理器里點(diǎn)擊任何文件, 系統(tǒng)都會(huì)試圖去執(zhí)行你的程序.
轉(zhuǎn)自 http://chaozhong84.spaces.live.com/blog/cns!FC149E9A3FC0182B!297.trak
【Android】【轉(zhuǎn)】Android Log Analysis
---------------------------------------------------
本文原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處,如有錯(cuò)誤之處歡迎指出
---------------------------------------------------
Get Log from Android System
adb bugreport > bugreport.txt
copy bugreport to the current directory.
bugreport里面包含了各種log信息,大部分log也可以通過直接運(yùn)行相關(guān)的程序來直接獲得.
步驟如下:
1.adb shell 2.進(jìn)入相關(guān)工具程式的目錄 3.執(zhí)行相關(guān)程式 4.得到相關(guān)信息
下面以輸出進(jìn)程信息為例 1.adb shell 2.輸入ps -P 3.可以看到相關(guān)進(jìn)程信息
Log Archive Analysis
1.bugreport
bugreport記錄android啟動(dòng)過程的log,以及啟動(dòng)后的系統(tǒng)狀態(tài),包括進(jìn)程列表,內(nèi)存信息,VM信息等等到.
2.bugreport結(jié)構(gòu)分析
(1)dumpstate
MEMORY INFO
獲取該log:讀取文件/proc/meminfo
系統(tǒng)內(nèi)存使用狀態(tài)
CPU INFO
獲取該log:執(zhí)行/system/bin/top -n 1 -d 1 -m 30 -t
系統(tǒng)CPU使用狀態(tài)
PROCRANK
獲取該log:執(zhí)行/system/bin/procrank
執(zhí)行/system/xbin/procrank后輸出的結(jié)果,查看一些內(nèi)存使用狀態(tài)
VIRTUAL MEMORY STATS
獲取該log:讀取文件/proc/vmstat
虛擬內(nèi)存分配情況
vmalloc申請(qǐng)的內(nèi)存則位于vmalloc_start~vmalloc_end之間,與物理地址沒有簡(jiǎn)單的轉(zhuǎn)換關(guān)系,雖然在邏輯上它們也是連續(xù)的,但是在物理上它們不要求連續(xù)。
VMALLOC INFO
獲取該log:讀取文件/proc/vmallocinfo
虛擬內(nèi)存分配情況
SLAB INFO
獲取該log:讀取文件/proc/slabinfo
SLAB是一種內(nèi)存分配器.這里輸出該分配器的一些信息
ZONEINFO
獲取該log:讀取文件/proc/zoneinfo
zone info
SYSTEM LOG(需要著重分析)
獲取該log:執(zhí)行/system/bin/logcat -v time -d *:v
會(huì)輸出在程序中輸出的Log,用于分析系統(tǒng)的當(dāng)前狀態(tài)
VM TRACES
獲取該log:讀取文件/data/anr/traces.txt
因?yàn)槊總€(gè)程序都是在各自的VM中運(yùn)行的,這個(gè)Log是現(xiàn)實(shí)各自VM的一些traces
EVENT LOG TAGS
獲取該log:讀取文件/etc/event-log-tags
EVENT LOG
獲取該log:執(zhí)行/system/bin/logcat -b events -v time -d *:v
輸出一些Event的log
RADIO LOG
獲取該log:執(zhí)行/system/bin/logcat -b radio -v time -d *:v
顯示一些無線設(shè)備的鏈接狀態(tài),如GSM,PHONE,STK(Satellite Tool Kit)...
NETWORK STATE
獲取該log:執(zhí)行/system/bin/netcfg (得到網(wǎng)絡(luò)鏈接狀態(tài))
獲取該log:讀取文件/proc/net/route (得到路由狀態(tài))
顯示網(wǎng)絡(luò)鏈接和路由
SYSTEM PROPERTIES
獲取該log:參考代碼實(shí)現(xiàn)
顯示一些系統(tǒng)屬性,如Version,Services,network...
KERNEL LOG
獲取該log:執(zhí)行/system/bin/dmesg
顯示Android內(nèi)核輸出的Log
KERNEL WAKELOCKS
獲取該log:讀取文件/proc/wakelocks
內(nèi)核對(duì)一些程式和服務(wù)喚醒和休眠的一些記錄
KERNEL CPUFREQ
(Linux kernel CPUfreq subsystem) Clock scaling allows you to change the clock speed of the CPUs on the fly.
This is a nice method to save battery power, because the lower the clock speed is, the less power the CPU consumes.
PROCESSES
獲取該log:執(zhí)行ps -P
顯示當(dāng)前進(jìn)程
PROCESSES AND THREADS
獲取該log:執(zhí)行ps -t -p -P
顯示當(dāng)前進(jìn)程和線程
LIBRANK
獲取該log:執(zhí)行/system/xbin/librank
剔除不必要的library
BINDER FAILED TRANSACTION LOG
獲取該log:讀取文件/proc/binder/failed_transaction_log
BINDER TRANSACTION LOG
獲取該log:讀取文件/proc/binder/transaction_log
BINDER TRANSACTIONS
獲取該log:讀取文件/proc/binder/transactions
BINDER STATS
獲取該log:讀取文件/proc/binder/stats
BINDER PROCESS STATE
獲取該log:讀取文件/proc/binder/proc/*
bind相關(guān)的一些狀態(tài)
FILESYSTEMS
獲取該log:執(zhí)行/system/bin/df
主要文件的一些容量使用狀態(tài)(cache,sqlite,dev...)
PACKAGE SETTINGS
獲取該log:讀取文件/data/system/packages.xml
系統(tǒng)中package的一些狀態(tài)(訪問權(quán)限,路徑...),類似Windows里面的一些lnk文件吧.
PACKAGE UID ERRORS
獲取該log:讀取文件/data/system/uiderrors.txt
錯(cuò)誤信息
KERNEL LAST KMSG LOG
最新kernel message log
LAST RADIO LOG
最新radio log
KERNEL PANIC CONSOLE LOG
KERNEL PANIC THREADS LOG
控制臺(tái)/線程的一些錯(cuò)誤信息log
BACKLIGHTS
獲取該log:獲取LCD brightness讀/sys/class/leds/lcd-backlight/brightness
獲取該log:獲取Button brightness讀/sys/class/leds/button-backlight/brightness
獲取該log:獲取Keyboard brightness讀/sys/class/leds/keyboard-backlight/brightness
獲取該log:獲取ALS mode讀/sys/class/leds/lcd-backlight/als
獲取該log:獲取LCD driver registers讀/sys/class/leds/lcd-backlight/registers
獲取相關(guān)亮度的一些信息
(2)build.prop
VERSION INFO輸出下列信息
當(dāng)前時(shí)間
當(dāng)前內(nèi)核版本:可以讀取文件(/proc/version)獲得
顯示當(dāng)前命令:可以讀取文件夾(/proc/cmdline)獲得
顯示系統(tǒng)build的一些屬性:可以讀取文件(/system/build.prop)獲得
輸出系統(tǒng)一些屬性
gsm.version.ril-impl
gsm.version.baseband
gsm.imei
gsm.sim.operator.numeric
gsm.operator.alpha
(3)dumpsys
執(zhí)行/system/bin/dumpsys后可以獲得這個(gè)log.
經(jīng)常會(huì)發(fā)現(xiàn)該log輸出不完整,因?yàn)榇a里面要求該工具最多只執(zhí)行60ms,可能會(huì)導(dǎo)致log無法完全輸出來.
可以通過修改時(shí)間參數(shù)來保證log完全輸出.
信息:
Currently running services
DUMP OF SERVICE services-name(running)
Log Code Analysis
Site: ."frameworks"base"cmds"dumpstate"
相關(guān)Log程序的代碼可以從上面目錄獲取
Log Analysis Experience
分析步驟
1.查看一些版本信息
確認(rèn)問題的系統(tǒng)環(huán)境
2.查看CPU/MEMORY的使用狀況
看是否有內(nèi)存耗盡,CPU繁忙這樣的背景情況出現(xiàn).
3.分析traces
因?yàn)閠races是系統(tǒng)出錯(cuò)以后輸出的一些線程堆棧信息,可以很快定位到問題出在哪里.
4.分析SYSTEM LOG
系統(tǒng)Log詳細(xì)輸出各種log,可以找出相關(guān)log進(jìn)行逐一分析
實(shí)例分析
下面分析我寫的一個(gè)測(cè)試?yán)?在OnCreate做一個(gè)死循環(huán),這樣主線程會(huì)被鎖住,在按下硬件的Back之后會(huì)出現(xiàn)ANR的錯(cuò)誤.
在traces中發(fā)現(xiàn)該程序的堆棧信息如下:
----- pid 20597 at 2010-03-15 01:29:53 -----
Cmd line: com.android.test
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=N obj=0x2aac6240 self=0xbda8
| sysTid=20597 nice=0 sched=0/0 cgrp=default handle=1877232296
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1306)
at java.lang.Thread.sleep(Thread.java:1286)
at android.os.SystemClock.sleep(SystemClock.java:114)
at com.android.test.main.onCreate(main.java:20)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
at android.app.ActivityThread.access$2200(ActivityThread.java:119)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #2" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c260 self=0x143860
| sysTid=20601 nice=0 sched=0/0 cgrp=default handle=1211376
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c1a0 self=0x14c980
| sysTid=20600 nice=0 sched=0/0 cgrp=default handle=1207920
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=N obj=0x2fb7a1e8 self=0x126cc0
| sysTid=20599 nice=0 sched=0/0 cgrp=default handle=1269048
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=N obj=0x2e31daf0 self=0x135c08
| sysTid=20598 nice=0 sched=0/0 cgrp=default handle=1268528
at dalvik.system.NativeStart.run(Native Method)
----- end 20597 -----
該文件的堆棧結(jié)構(gòu)從下往上進(jìn)行分析
(1)棧底at dalvik.system.NativeStart.run(Native Method)
系統(tǒng)為當(dāng)前的task(應(yīng)用程式)啟動(dòng)一個(gè)專用的虛擬機(jī)
(2) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
Activity Services是在后臺(tái)負(fù)責(zé)管理Activity,它此時(shí)將測(cè)試?yán)拥腁ctivity啟動(dòng)起來了
(3)at com.android.test.main.onCreate(main.java:20)
啟動(dòng)測(cè)試程序
(4)棧頂at java.lang.VMThread.sleep(Native Method)
線程被sleep掉了,所以無法響應(yīng)用戶,出現(xiàn)ANR錯(cuò)誤.
上面是對(duì)一個(gè)非常簡(jiǎn)單的問題的分析.
如果遇到比較復(fù)雜的問題還需要詳細(xì)分析SYSTEM LOG.
1.比如網(wǎng)絡(luò)異常,要通過SYSTEM LOG里面輸出的網(wǎng)絡(luò)鏈接信息來判斷網(wǎng)絡(luò)狀態(tài)
2.數(shù)據(jù)傳輸,網(wǎng)絡(luò)鏈接等耗時(shí)的操作需要分析SYSTEM LOG里面ActivityManager的響應(yīng)時(shí)間
轉(zhuǎn)自:http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx
http://hi.baidu.com/donghaozheng/blog/item/30a00d4f9fca873baec3ab69.html
在 android 的API中有提供 SystemClock.setCurrentTimeMillis()函數(shù)來修改系統(tǒng)時(shí)間,可惜無論你怎么調(diào)用這個(gè)函數(shù)都是沒用的,無論模擬器還是真機(jī),在logcat中總會(huì)得到"Unable to open alarm driver: Permission denied ".這個(gè)函數(shù)需要root權(quán)限或者運(yùn)行與系統(tǒng)進(jìn)程中才可以用。
本來以為就沒有辦法在應(yīng)用程序這一層改系統(tǒng)時(shí)間了,后來在網(wǎng)上搜了好久,知道這個(gè)目的還是可以達(dá)到的。
第一個(gè)方法簡(jiǎn)單點(diǎn),不過需要在Android系統(tǒng)源碼的環(huán)境下用make來編譯:
1. 在應(yīng)用程序的AndroidManifest.xml中的manifest節(jié)點(diǎn)中加入android:sharedUserId="android.uid.system"這個(gè)屬性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform這一行
3. 使用mm命令來編譯,生成的apk就有修改系統(tǒng)時(shí)間的權(quán)限了。
第二個(gè)方法麻煩點(diǎn),不過不用開虛擬機(jī)跑到源碼環(huán)境下用make來編譯:
1. 同上,加入android:sharedUserId="android.uid.system"這個(gè)屬性。
2. 使用eclipse編譯出apk文件,但是這個(gè)apk文件是不能用的。
3. 用壓縮軟件打開apk文件,刪掉META-INF目錄下的CERT.SF和CERT.RSA兩個(gè)文件。
4. 使用目標(biāo)系統(tǒng)的platform密鑰來重新給apk文件簽名。這步比較麻煩,首先找到密鑰文件,在我的Android源碼目錄中的位置是"build\target\product\security",下面的platform.pk8和platform.x509.pem兩個(gè)文件。然后用Android提供的Signapk工具來簽名,signapk的源代碼是在"build\tools\signapk"下,用法為"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用絕對(duì)路徑防止找不到,也可以修改源代碼直接使用。
這樣最后得到的apk和第一個(gè)方法是一樣的。
最后解釋一下原理,首先加入android:sharedUserId="android.uid.system"這個(gè)屬性。通過Shared User id,擁有同一個(gè)User id的多個(gè)APK可以配置成運(yùn)行在同一個(gè)進(jìn)程中。那么把程序的UID配成android.uid.system,也就是要讓程序運(yùn)行在系統(tǒng)進(jìn)程中,這樣就有權(quán)限來修改系統(tǒng)時(shí)間了。
只是加入U(xiǎn)ID還不夠,如果這時(shí)候安裝APK的話發(fā)現(xiàn)無法安裝,提示簽名不符,原因是程序想要運(yùn)行在系統(tǒng)進(jìn)程中還要有目標(biāo)系統(tǒng)的platform key,就是上面第二個(gè)方法提到的platform.pk8和platform.x509.pem兩個(gè)文件。用這兩個(gè)key簽名后apk才真正可以放入系統(tǒng)進(jìn)程中。第一個(gè)方法中加入LOCAL_CERTIFICATE := platform其實(shí)就是用這兩個(gè)key來簽名。
這也有一個(gè)問題,就是這樣生成的程序只有在原始的Android系統(tǒng)或者是自己編譯的系統(tǒng)中才可以用,因?yàn)檫@樣的系統(tǒng)才可以拿到platform.pk8和platform.x509.pem兩個(gè)文件。要是別家公司做的Android上連安裝都安裝不了。試試原始的Android中的key來簽名,程序在模擬器上運(yùn)行OK,不過放到G3上安裝直接提示"Package ... has no signatures that match those in shared user android.uid.system",這樣也是保護(hù)了系統(tǒng)的安全。
最最后還說下,這個(gè)android:sharedUserId屬性不只可以把a(bǔ)pk放到系統(tǒng)進(jìn)程中,也可以配置多個(gè)APK運(yùn)行在一個(gè)進(jìn)程中,這樣可以共享數(shù)據(jù),應(yīng)該會(huì)很有用的。
博主補(bǔ)充:
signapk編譯結(jié)束后在 android目錄下/out/host/linux-x86/framework/signapk.jar
使用方法:java -jar signapk.jar platform.x509.pem platform.pk8 test.apk test_signed.apk
實(shí)踐證明,第二種方法不需要?jiǎng)h掉META-INF目錄下的CERT.SF和CERT.RSA兩個(gè)文件,直接signapk就可以。
|
(1) Looper類別用來為一個(gè)線程開啟一個(gè)消息循環(huán)。默認(rèn)情況下Android中新誕生的線程是沒有開啟消息循環(huán)的。(主線程除外,主線程系統(tǒng)會(huì)自動(dòng)為其創(chuàng)建Looper對(duì)象,開啟消息循環(huán))
Looper對(duì)象通過MessageQueue來存放消息和事件。一個(gè)線程只能有一個(gè)Looper,對(duì)應(yīng)一個(gè)MessageQueue。
(2) 通常是通過Handler對(duì)象來與Looper交互的。Handler可看做是Looper的一個(gè)接口,用來向指定的Looper發(fā)送消息及定義處理方法。
默認(rèn)情況下Handler會(huì)與其被定義時(shí)所在線程的Looper綁定,比如,在主線程中定義,其是與主線程的Looper綁定。
mainHandler = new Handler() 等價(jià)于new Handler(Looper.myLooper()).
Looper.myLooper():Return the Looper object associated with the current thread 獲取當(dāng)前進(jìn)程的looper對(duì)象。
還有一個(gè)類似的 Looper.getMainLooper() 用于獲取主線程的Looper對(duì)象。
(3) 在非主線程中直接new Handler() 會(huì)報(bào)如下的錯(cuò)誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主線程中默認(rèn)沒有創(chuàng)建Looper對(duì)象,需要先調(diào)用Looper.prepare()啟用Looper。
(4) Looper.loop(); 讓Looper開始工作,從消息隊(duì)列里取消息,處理消息。
注意:寫在Looper.loop()之后的代碼不會(huì)被執(zhí)行,這個(gè)函數(shù)內(nèi)部應(yīng)該是一個(gè)循環(huán),當(dāng)調(diào)用mHandler.getLooper().quit()后,loop才會(huì)中止,其后的代碼才能得以運(yùn)行。
(5) 基于以上知識(shí),可實(shí)現(xiàn)主線程給子線程(非主線程)發(fā)送消息。
把下面例子中的mHandler聲明成類成員,在主線程通過mHandler發(fā)送消息即可。
(6) Android官方文檔中Looper的介紹:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation ofprepare() and loop() to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
px (pixels) 像素
dip (device independent pixels) 設(shè)備獨(dú)立像素
sp (scaled pixels - best for text size ) 放大像素,對(duì)文本大小最好
pt (points) 點(diǎn)
in (inches) 英寸
mm (millimeters) 毫米
很多網(wǎng)友可能發(fā)現(xiàn)在Android的layout文件中l(wèi)ayout_width或layout_height有時(shí)候可能會(huì)指定具體的單位,比如有時(shí)候?yàn)閜x、dip或者sp等等。下面android123把常見的單位做下簡(jiǎn)單的介紹,比如說
px (pixels)像素 -- 一般我們HVGA代表320x480像素,這個(gè)用的比較多。
dip或dp (device independent pixels)設(shè)備獨(dú)立像素 -- 這個(gè)和設(shè)備硬件有關(guān),一般我們?yōu)榱酥С諻VGA、HVGA和QVGA cwj推薦使用這個(gè),不依賴像素。
sp (scaled pixels — best for text size)放大像素-- 主要處理字體的大小。
下面的幾個(gè)是不常用的,大家也知道這里android123就不再過多的贅述。
in (inches)英寸
mm (millimeters)毫米
pt (points)點(diǎn)
px像素如何轉(zhuǎn)為dip設(shè)備獨(dú)立像素
最近有網(wǎng)友問如何將px像素轉(zhuǎn)為dip獨(dú)立設(shè)備像素,由于Android的設(shè)備分辨率眾多,目前主流的為wvga,而很多老的設(shè)備為hvga甚至低 端的qvga,對(duì)于兼容性來說使用dip無非是比較方便的,由于他和分辨率無關(guān)和屏幕的密度大小有關(guān),所以推薦使用,不過這里android123提示大 家,ophone os的手機(jī)對(duì)于dip的支持糟糕透了,顯示的結(jié)果會(huì)放大很多,同時(shí)黑色的主題會(huì)導(dǎo)致常規(guī)的黑色文字讓用戶無法分辨。
px= (int) (dip*density+0.5f) //這里android開發(fā)網(wǎng)提示大家很多網(wǎng)友獲取density的方法存在問題,從資源中獲取的是靜態(tài)定義的,一般為1.0對(duì)于HVGA是正好的,而對(duì)于wvga這樣的應(yīng)該從WindowsManager中獲取,WVGA為1.5
QVGA HVGA WVGA區(qū)別
文章分類:移動(dòng)開發(fā)
QVGA即"Quarter VGA"。顧名思義即VGA的四分之一尺寸,亦即在液晶屏幕(LCD)上輸出的分辨率是240×320像素。QVGA支持屏幕旋轉(zhuǎn),可以開發(fā)出相應(yīng)的程序,以顯示旋轉(zhuǎn)90°、180°、270°屏幕位置。由HandEra公司發(fā)布。多用于手持/移動(dòng)設(shè)備。 需要說明的是有些媒體把QVGA屏幕當(dāng)成與TFT和TFD等LCD材質(zhì)相同的東西是錯(cuò)誤的,QVGA屏幕的說法多見與日本的一些手機(jī)中,目前采用微軟Pocket PC操作系統(tǒng)的智能手機(jī)屏幕也大多是320×240像素的QVGA屏幕。 所謂QVGA液晶技術(shù),就是在液晶屏幕上輸出的分辨率是240×320的液晶輸出方式。這個(gè)分辨率其實(shí)和屏幕本身的大小并沒有關(guān)系。比如說,如果2.1英寸液晶顯示屏幕可以顯示240×320分辨率的圖像,就叫做“QVGA 2.1英寸液晶顯示屏”;如果3.8英寸液晶顯示屏幕可以顯示240×320的圖像,就叫做“QVGA 3.8英寸液晶顯示屏”,以上兩種情況雖然具有相同的分辨率,但是由于尺寸的不同實(shí)際的視覺效果也不同,一般 HVGA 即VGA(640*480)的一半,分辨率為(480*320),(3:2寬高比) 它是用于各種各樣的PDA設(shè)備,首先是2002年的索尼Clie PEG - NR70, 來說屏幕小的一個(gè)畫面自然也會(huì)細(xì)膩一些。 WVGA 數(shù)碼產(chǎn)品屏幕材質(zhì)的一種,VGA的另一種形式,比VGA分辨率高,別名 : Wide VGA, ,其分辯率為800×480象素。是擴(kuò)大了VGA(640×480)的分辨率。應(yīng)用于PDA和手機(jī)等,因?yàn)楹芏嗑W(wǎng)頁的寬度都是800,所以WVGA的屏幕會(huì)更加適和于瀏覽網(wǎng)頁,可以說是未來手持設(shè)備的分辨率的大趨勢(shì)
drawable-hdpi(高分辨率)目錄下
這個(gè)主要是為了支持多分辨率的.
hdpi里面主要放高分辨率的圖片,如WVGA (480x800),FWVGA (480x854)
mdpi里面主要放中等分辨率的圖片,如HVGA (320x480)
ldpi里面主要放低分辨率的圖片,如QVGA (240x320)
系統(tǒng)會(huì)根據(jù)機(jī)器的分辨率來分別到這幾個(gè)文件夾里面去找對(duì)應(yīng)的圖片