In order to set a breakpoint in a dependent library and break at the main project, you will need first set the breakpoint in the library and then change the scope of the breakpoint to user.
Launch the main project will hit the breakpoint you just set in the library project.
There are lots of helpful information available on internet, so just share some notes I found useful during application development, to contribute back to the community. Jonathan in Toronto
Tuesday, November 8, 2011
Iphone simulator folder in Lion with Xcode 4.2
By default, the library folder under user is hidden in Lion with Xcode 4.2, so you will not be able to access the iPhone simulator folder shown below.
/Users/(your user name)/Library/Application Support/iPhone Simulator
To show the library folder, run the following command from terminal window:
chflags nohidden ~/Library/
Note the library folder must be the one under your name, not the one under root.
/Users/(your user name)/Library/Application Support/iPhone Simulator
To show the library folder, run the following command from terminal window:
chflags nohidden ~/Library/
Note the library folder must be the one under your name, not the one under root.
Saturday, November 5, 2011
Fresh installation of Lion on Mac without CD or USB stick
Lion has to be upgraded on Mac, however, you may want to have a fresh install of Lion to get rid of the old application or settings from the Snow Leopard. The following steps can be used to make a refresh Lion installation.
1. Upgrade Snow Leopard to Lion as Apple suggested from app store (paying for $29)
2. Reboot Mac while holding option key
3. Select the restore disk for starting
4. Select Disk Utility and erase the main hard disk drive. This may erase the old Snow Leopard.
5. Restore Lion, it will start a refresh Lion installation.
Cheers
Jonathan
1. Upgrade Snow Leopard to Lion as Apple suggested from app store (paying for $29)
2. Reboot Mac while holding option key
3. Select the restore disk for starting
4. Select Disk Utility and erase the main hard disk drive. This may erase the old Snow Leopard.
5. Restore Lion, it will start a refresh Lion installation.
Cheers
Jonathan
Sunday, October 30, 2011
Property and Synthesize in ObjectC and Xcode
Property in ObjectC and xCode is quite different from what java or C# or C++ uses property. The following highlights the difference
1. What "@property float myValue;" does
When defining property myValue in header file, it says, there will be a myValue and setMyValue method available in implementation file. In addition, those two methods can be invoked using myObject.myValue to get and set.
Notice when property is defined, there is no data member involved, the value is totally controlled by myValue and setMyValue method
Update to now, everything is quite clear, and nothing is that different from C# or java.
2. What "@synthesize myValue;" does
@synthesize is totally new to java or c#. It does more harm then help to objectC. As program is not about simplifying of coding, it is about logic consistence. It is better to let developer explicitly specifies the expected behavior than magically doing so underneath.
So what @synthesize does as shown below?
head file:
@property float myValue;"
implementation file:
"@synthesize myValue;"
The above code silently create the imaged implementation of myValue and setMyValue for the myValue property. And it also silently create the data member to hold the myValue's data, so that the code can first set the value and then get the value back without defining a data member to store the value. Developers actually do not know where data is stored, they just know it is stored in somewhere.
Now let add a data member myValue in the header file, and see what magic will happen. As long as the data member's type and name match the property's type and name, then @synthesize will automatically associate the imaged implementation to the data member, so the data are actually stored in the new data member.
Up to now, things still look fine although not appreciated. It really starts to mess up when adding property method implementation as shown in the following code:
Header file
@interface Property : NSObject {
float myInsideValue;
}
@property float myValue;
-(float) myMethod:(float)m;
@end
Implementation file:
@implementation Property
@synthesize myValue;
- (float) myValue
{
return myInsideValue;
}
- (void) setMyValue:(float) v
{
myInsideValue =v;
}
-(float) myMethod:(float)m
{
myValue = m;
return myValue;
}
@end
The major problem is @synthesize silently adds a imagined data member when myValue is accessed inside the interface implementation file, so inside myMethod accessing myValue does not go through the property methods. While, when myValue is accessed outside the interface implementation file, myValue is accessed through property method. As the result, inside the implementation file, myValue's value is different from myInsideValue's value.
In order to avoid this kind of confusion, a simple rule is do not use property method and synthesize together, and it is preferred to use property method to be consistent with java or c#. If subclass for property is involved, it is much better to deal with property method than the "smart" syntheisze syntex.
3. Inside the class only use data member
4. property and subclass
1. What "@property float myValue;" does
When defining property myValue in header file, it says, there will be a myValue and setMyValue method available in implementation file. In addition, those two methods can be invoked using myObject.myValue to get and set.
Notice when property is defined, there is no data member involved, the value is totally controlled by myValue and setMyValue method
Update to now, everything is quite clear, and nothing is that different from C# or java.
2. What "@synthesize myValue;" does
@synthesize is totally new to java or c#. It does more harm then help to objectC. As program is not about simplifying of coding, it is about logic consistence. It is better to let developer explicitly specifies the expected behavior than magically doing so underneath.
So what @synthesize does as shown below?
head file:
@property float myValue;"
implementation file:
"@synthesize myValue;"
The above code silently create the imaged implementation of myValue and setMyValue for the myValue property. And it also silently create the data member to hold the myValue's data, so that the code can first set the value and then get the value back without defining a data member to store the value. Developers actually do not know where data is stored, they just know it is stored in somewhere.
Now let add a data member myValue in the header file, and see what magic will happen. As long as the data member's type and name match the property's type and name, then @synthesize will automatically associate the imaged implementation to the data member, so the data are actually stored in the new data member.
Up to now, things still look fine although not appreciated. It really starts to mess up when adding property method implementation as shown in the following code:
Header file
@interface Property : NSObject {
float myInsideValue;
}
@property float myValue;
-(float) myMethod:(float)m;
@end
Implementation file:
@implementation Property
@synthesize myValue;
- (float) myValue
{
return myInsideValue;
}
- (void) setMyValue:(float) v
{
myInsideValue =v;
}
-(float) myMethod:(float)m
{
myValue = m;
return myValue;
}
@end
The major problem is @synthesize silently adds a imagined data member when myValue is accessed inside the interface implementation file, so inside myMethod accessing myValue does not go through the property methods. While, when myValue is accessed outside the interface implementation file, myValue is accessed through property method. As the result, inside the implementation file, myValue's value is different from myInsideValue's value.
In order to avoid this kind of confusion, a simple rule is do not use property method and synthesize together, and it is preferred to use property method to be consistent with java or c#. If subclass for property is involved, it is much better to deal with property method than the "smart" syntheisze syntex.
3. Inside the class only use data member
4. property and subclass
Sunday, October 2, 2011
Upgrade the version of Blackberry persistent store class
When upgrading the version of Blackberry persistent store, like adding or removing a instance member in the persistent class, the saved persistent data will be automatically deleted by system.
To handle the version upgrading while storing the data in a single version instead of multiple versions of persistent classes, the application needs to keep the code of all older versions of persistent store in order to load the older data, and also upgrade the old version of data to latest version.
The logic are as follows:
VersionKeyArray =
{
OlderVersionKey1;
OlderVersionKey2;
LatestVersionKey3;
}
CurrentVersionKey = VersionJeyArray.LatestVersionKey3;
while (currentVersionKey != NULL)
{
get stored persistent object;
if (persistent object != NULL )
{
if ( is not the latest version )
{
read the older version of persistent data
Convert to the new version, this may involves crossing multiple versions
persist the new version of data
delete the older version of data
break;
}
}
go to the next older version key
}
//when the code gets here, we know we have the latest version of data
process the load persistent data if it is not null
To handle the version upgrading while storing the data in a single version instead of multiple versions of persistent classes, the application needs to keep the code of all older versions of persistent store in order to load the older data, and also upgrade the old version of data to latest version.
The logic are as follows:
VersionKeyArray =
{
OlderVersionKey1;
OlderVersionKey2;
LatestVersionKey3;
}
CurrentVersionKey = VersionJeyArray.LatestVersionKey3;
while (currentVersionKey != NULL)
{
get stored persistent object;
if (persistent object != NULL )
{
if ( is not the latest version )
{
read the older version of persistent data
Convert to the new version, this may involves crossing multiple versions
persist the new version of data
delete the older version of data
break;
}
}
go to the next older version key
}
//when the code gets here, we know we have the latest version of data
process the load persistent data if it is not null
Tuesday, September 13, 2011
Variable length arguments for javascript method
When creating javascrip method, if the parameters passed by caller may be different by any reason, an easy solution is just defining the parameters to empty, then inside the javascript method, accessing the actual parameter from the implicit argument variable.
The arguments variable inside the called function is an array containing the values of all the arguments passed to the function by caller, as shown in the following example:
function test()
{
alert(arguments[1]);
}
test("0","1","2");
John
The arguments variable inside the called function is an array containing the values of all the arguments passed to the function by caller, as shown in the following example:
function test()
{
alert(arguments[1]);
}
test("0","1","2");
John
Missing closing script tag in html causes javascript runtime error: Object expected
An runtime error: Object expected was returned when testing a simple function in html page's onLoad method. It turns out the error is due to missing closing script tag included
[head]
[script src="testcase.js" /]
[script type="text/javascript"
function callme() {alert("hi");}
[/script]
[/head]
[body onload="callme()"]
After adding the closing tag as shown below, the javascript method callme works properly.
[head]
[script src="testcase.js"] [/script]
[script type="text/javascript"
function callme() {alert("hi");}
[/script]
[/head]
[body onload="callme()"]
John
[head]
[script src="testcase.js" /]
[script type="text/javascript"
function callme() {alert("hi");}
[/script]
[/head]
[body onload="callme()"]
After adding the closing tag as shown below, the javascript method callme works properly.
[head]
[script src="testcase.js"] [/script]
[script type="text/javascript"
function callme() {alert("hi");}
[/script]
[/head]
[body onload="callme()"]
John
Wednesday, June 15, 2011
Property Attribute for iphone App
The following are some attribute used for property definition:
[assign]
This attribute indicates the property uses assignment in the property’s setter. No release to be called to the old value, and no retain to be called on the new value.
[retain]
This attribute indicates the property calls release to the old value, and retain on the new value.
[copy]
This attribute indicates the property calls release to the old value, and then allocate and copy a new object to the new value. The copy operation will retain on the newly created object.
[nonatomic]
This attribute indicate that the property’s accessor methods are not thread safe.. So do not access this property from multi-threads
[assign]
This attribute indicates the property uses assignment in the property’s setter. No release to be called to the old value, and no retain to be called on the new value.
[retain]
This attribute indicates the property calls release to the old value, and retain on the new value.
[copy]
This attribute indicates the property calls release to the old value, and then allocate and copy a new object to the new value. The copy operation will retain on the newly created object.
[nonatomic]
This attribute indicate that the property’s accessor methods are not thread safe.. So do not access this property from multi-threads
When the variable or data member needs to be released for iPhone
Basically, all variable and data members that is derived from NSObject needs to be explicitly release in iphone applications. When the variable or data member goes out of scope, the application or OS will not release it automatically, as all variable or data members are allocated in heap instead of stack. There is no concept of stack in objective C, so none of the variable or data member can be cleaned up automatically.
For local variable of NSObject in a method, releasing the variable before exiting the method.
For property, as the setter will release its current property value and retain the new value, so need to release the property value when the object instance is deallocated.
For instance variable, same as property, release the value when the object instance is deallocated
Certainly, if the variable or variable is changed in the middle, the old value needs to be released and the new value needs to be retained.
There are some exceptions due to compiler optimization, particularly for NSString objects, which may cause confusion to developers. For example, NSString object created with
[[NSString alloc] initWithString@"abc"] or [NSString StringWithString] has a retain count of 2147483647 instead of 1. The reason is the returned NSString just points to immutable constant NSString object passed in, which does not need to be released. However, NSString object created with [[NSString alloc] initWithUTF8String:"abc"] will need developer to release it. The IOS reference document does not mention anything about this kind of difference, and the only clue available is checking retainCount of the returned object.
In addition, based the memory management rules from Apple, release method should be called for [[NSString alloc] initWithString@"abc"], althoug we know actually it does nothing.
- You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
- You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (specifically: when the used autorelease pool receives a drain message—to understand when this will be, see “Autorelease Pools”).
For local variable of NSObject in a method, releasing the variable before exiting the method.
For property, as the setter will release its current property value and retain the new value, so need to release the property value when the object instance is deallocated.
For instance variable, same as property, release the value when the object instance is deallocated
Certainly, if the variable or variable is changed in the middle, the old value needs to be released and the new value needs to be retained.
There are some exceptions due to compiler optimization, particularly for NSString objects, which may cause confusion to developers. For example, NSString object created with
[[NSString alloc] initWithString@"abc"] or [NSString StringWithString] has a retain count of 2147483647 instead of 1. The reason is the returned NSString just points to immutable constant NSString object passed in, which does not need to be released. However, NSString object created with [[NSString alloc] initWithUTF8String:"abc"] will need developer to release it. The IOS reference document does not mention anything about this kind of difference, and the only clue available is checking retainCount of the returned object.
In addition, based the memory management rules from Apple, release method should be called for [[NSString alloc] initWithString@"abc"], althoug we know actually it does nothing.
- You take ownership of an object if you create it using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message.
- You use release or autorelease to relinquish ownership of an object. autorelease just means “send a release message in the future” (specifically: when the used autorelease pool receives a drain message—to understand when this will be, see “Autorelease Pools”).
Sunday, May 29, 2011
Static variable in C/C++
Thanks to the iPhone development platform, the C++ once again gets the notice of mobile developers. This post talks few issues about static keyword in c/c++.
1. Using static for variable in file scope
If the same named variable is defined in multiple files, compiler will report an error due to the duplicated definition. Adding static for the variable definition will make the variable's scope to the current file, so that they will not conflict with each other. Note, the static variable defined in each file has its own instance. Changing the static variable's value in one file will not affect another file's variable value.
If you want to share the same instance, using extern keywork.
2. Using static for variable in class scope
This is quite easy to understanding, since it is similar to .net or java. The variable belongs to the class instead of a particular class instance.
3. Using static for variable in method scope
The variable will be initialized once, and each time when the mothod gets called, the same instance will be used. It is more useful in c, as in c++, we can just define a class member to do the same thing.
In all cases, if adding const in the definition, then the variable can not be updated once it is initialized.
Jonathan
1. Using static for variable in file scope
If the same named variable is defined in multiple files, compiler will report an error due to the duplicated definition. Adding static for the variable definition will make the variable's scope to the current file, so that they will not conflict with each other. Note, the static variable defined in each file has its own instance. Changing the static variable's value in one file will not affect another file's variable value.
If you want to share the same instance, using extern keywork.
2. Using static for variable in class scope
This is quite easy to understanding, since it is similar to .net or java. The variable belongs to the class instead of a particular class instance.
3. Using static for variable in method scope
The variable will be initialized once, and each time when the mothod gets called, the same instance will be used. It is more useful in c, as in c++, we can just define a class member to do the same thing.
In all cases, if adding const in the definition, then the variable can not be updated once it is initialized.
Jonathan
Saturday, April 16, 2011
Create view without InterfaceBuilder for iPhone
Although InterfaceBuilder is an important tool for iPhone development, the tool is not as intuitive to use as Visual Studio UI designer.
To help understand what interfacebuilder does, we can create the interface without using InterfaceBuilder, and then comparing the corresponding steps done by InterfaceBuilder.
Steps to add a ViewController without using InterfaceBuild:
1. Create a Window based iPhone application
2. Add a new UIViewController subclass in the project. Do not select "With XIB for user interface" checkbox
3. In the UIViewContollerSubclass' viewDidLoad method, create some UI elements and then add them into UIViewController.view collection by [self.view addSubview:uiElement] method.
4. In WindowAppDelegate.m didFinishLaunchingWithOptions method, create a instance of this new UIViewControllerSubClass instance, add it into appliation's main window with [window addSubview:uiViewControllerInstance.view].
Comparing with InterfaceBuilder to do the same thing, the following steps are required
1. If a UI sub class is created in the app for a ui element, like UIViewControllerSubClass, then the identity class of the UI element added in InterfaceBuilder needs to set the corresponding sub class with Identity Inspector.
2. For UIViewController object, use Attribute Inspector to set the NIB name to load the xib file, this associates the xib file with the UI control added in InterfaceBuilder.
3. Any IBOutlet property , or IBAction defined in .h file need to be associated with the corresponding ui element added in InterfaceBuilder.
4. File owner is the class that will load the xib file at runtime, for MainWindow.xib, it must be UIApplication classor its subclass. For UIViewController.xib, it must be a subclass of UIViewController class.
Jonathan
To help understand what interfacebuilder does, we can create the interface without using InterfaceBuilder, and then comparing the corresponding steps done by InterfaceBuilder.
Steps to add a ViewController without using InterfaceBuild:
1. Create a Window based iPhone application
2. Add a new UIViewController subclass in the project. Do not select "With XIB for user interface" checkbox
3. In the UIViewContollerSubclass' viewDidLoad method, create some UI elements and then add them into UIViewController.view collection by [self.view addSubview:uiElement] method.
4. In WindowAppDelegate.m didFinishLaunchingWithOptions method, create a instance of this new UIViewControllerSubClass instance, add it into appliation's main window with [window addSubview:uiViewControllerInstance.view].
Comparing with InterfaceBuilder to do the same thing, the following steps are required
1. If a UI sub class is created in the app for a ui element, like UIViewControllerSubClass, then the identity class of the UI element added in InterfaceBuilder needs to set the corresponding sub class with Identity Inspector.
2. For UIViewController object, use Attribute Inspector to set the NIB name to load the xib file, this associates the xib file with the UI control added in InterfaceBuilder.
3. Any IBOutlet property , or IBAction defined in .h file need to be associated with the corresponding ui element added in InterfaceBuilder.
4. File owner is the class that will load the xib file at runtime, for MainWindow.xib, it must be UIApplication classor its subclass. For UIViewController.xib, it must be a subclass of UIViewController class.
Jonathan
Wednesday, April 6, 2011
How to hide and show soft keyboard on iPhone simulator
When testing with iPhone simulator, occasionaly, you will need to show or hide the soft keyboard. To do so, go to IOS simulator's Hardware menu, and select "Simulator Hardware Keyboard" submenu, it will toggle the soft keyboard's state.
Jonathan
Jonathan
Sunday, April 3, 2011
Protocol in Objective C
Protocol in Objective C is quite similar to interface in java or .net, so there is not much to say about it.
To define a protocol in a class header as
@protocol MyProtocol
-(void) myfunction;
@end
The header file of the class that implements a protocol looks like the following, notice the syntax is quite similar to category but uses angle bracket instead of parenthesis.
@interface MyUserClass : NSObject.
Jonathan
To define a protocol in a class header as
@protocol MyProtocol
-(void) myfunction;
@end
The header file of the class that implements a protocol looks like the following, notice the syntax is quite similar to category but uses angle bracket instead of parenthesis.
@interface MyUserClass : NSObject
Jonathan
Category in Objective C
Category in Objective C is a new concept to C++ developer. The catetory must associate with any existing class, even if the class implementation is not accessible to you. Note that a cateory can not declare additional instance variables for the class. It can only include instance methods.
While category is similar to subclass, the difference is with category, the new methods directly added into the original class without creating a new derived class.
The syntax is
Header file (name convention is "classname+categoryname.h"):
#interface "ClassName.h"
@interface ClassName (CategoryName )
- (int) categoryFunction;
@end
Implementation file (name convention is "classname+categoryname.m"):
#import "classnmae+categoryname.m"
@implementation ClassName (CategoryName )
- (int) categoryFunction {
return 0;
}
@end
Note another Objective C feature: Extension is like cateory but without an name, the extension methods must be implemented in the main @implementation block of the corresponding class. The extension example is shown below:
Header file ( "classname.h")
@interface ClassName ()
- (int) extensionFunction;
@end
implementation file ("classname.m")
@implementation classname
... class methods implementation
- (int) extensionFunction {
return 1;
}
@end
Jonathan
While category is similar to subclass, the difference is with category, the new methods directly added into the original class without creating a new derived class.
The syntax is
Header file (name convention is "classname+categoryname.h"):
#interface "ClassName.h"
@interface ClassName (CategoryName )
- (int) categoryFunction;
@end
Implementation file (name convention is "classname+categoryname.m"):
#import "classnmae+categoryname.m"
@implementation ClassName (CategoryName )
- (int) categoryFunction {
return 0;
}
@end
Note another Objective C feature: Extension is like cateory but without an name, the extension methods must be implemented in the main @implementation block of the corresponding class. The extension example is shown below:
Header file ( "classname.h")
@interface ClassName ()
- (int) extensionFunction;
@end
implementation file ("classname.m")
@implementation classname
... class methods implementation
- (int) extensionFunction {
return 1;
}
@end
Jonathan
Sunday, March 27, 2011
Object inheritance with Javascript
Prototype can be used to define data member and function member to a object. It also is used to realize inheritance for javascript. In order to inherit an object from another object, we set the new the new function's prototype to the existing function as show below:
function base()
{ this.inbase = 2;}
base.prototype.inbaseProto = 3;
base.prototype.getint = function()
{
return 3;
}
derived.prototype = new base;
function derived()
{ this.inderived = 4;}
derived.prototype.inderivedProto = 5;
x = new derived;
s = x.getint();
alert(base.inbase + ', ' + x.inbaseProto + ', ' + x.inderived + ', ' + x.inderivedProto + ', ' + s );
The result is "2, 3, 4, 5, 3";
Jonathan
function base()
{ this.inbase = 2;}
base.prototype.inbaseProto = 3;
base.prototype.getint = function()
{
return 3;
}
derived.prototype = new base;
function derived()
{ this.inderived = 4;}
derived.prototype.inderivedProto = 5;
x = new derived;
s = x.getint();
alert(base.inbase + ', ' + x.inbaseProto + ', ' + x.inderived + ', ' + x.inderivedProto + ', ' + s );
The result is "2, 3, 4, 5, 3";
Jonathan
Use prototype to make javascript object oriented
Unlike other object oriented language, javascript does not support the common way of defining data member or function member. However, this can be supported in javascript by using prototype.
For javascript, when a function is defined, it automatcally gets a data member of prototype, which also has a constructor method by default- i.e the function itself. The constructor is used to create the instance of the object. If any data members or function members are defined on this prototype object, then all instances created by the function will automatically have those data members and function members defined, similar to other object oriented lanaguages, the code is shown below,
function f(){
}
f.prototype.datamember=3.14159;
// create the object method
function f2(o){
alert(o);
}
f.prototype.funcmember=f2;
Note for prebuild types, only object, image, string, data and array can have their prototype changed to add new data members and function members, which means you can extend new function into those prebuild types. With the following code, then all instance of object will have the newprop as 123.
Object.prototype.newprop = "123";
Note if a same named property is defined in both object instance itself and object propotype, then the object instance property will take priority.
Jonathan
For javascript, when a function is defined, it automatcally gets a data member of prototype, which also has a constructor method by default- i.e the function itself. The constructor is used to create the instance of the object. If any data members or function members are defined on this prototype object, then all instances created by the function will automatically have those data members and function members defined, similar to other object oriented lanaguages, the code is shown below,
function f(){
}
f.prototype.datamember=3.14159;
// create the object method
function f2(o){
alert(o);
}
f.prototype.funcmember=f2;
Note for prebuild types, only object, image, string, data and array can have their prototype changed to add new data members and function members, which means you can extend new function into those prebuild types. With the following code, then all instance of object will have the newprop as 123.
Object.prototype.newprop = "123";
Note if a same named property is defined in both object instance itself and object propotype, then the object instance property will take priority.
Jonathan
Function object and this in javascript
Unlike other languages, function in javascript is an object same as other instance object. For example, if the following function is defined
function f(m,n) {
this.x = m;
this.y = n;
}
Then calling
var o1 = f;
Then the type of o is an object that represents the function. It is not a instance that is created by the f function.
Now let us see what happens if calling
var o2 = new f;
This time, the function serves as the construct to create a instance . The instance has two data member x, and y, whose values are not initialized. To set the data member values, calling
var o3 = new f(1, 2);
Now try to use the function in a different way as showing below
var o3 = f(2, 3);
This time, the function f is not used as a constructor, instead it is just a normal javascript method call, inside the function f, this pointer points to the window object of the current html page, and it just sets two new data members to the window object.
Another thing unique in javascript is, although any object instance can add new data members by just calling assigning operation as below
this.x = somevalue;
It can not do so to directly call a javascript funtion on an instance object. Instead, it must first assign the function to the instance's member before calling the function on it.
this.f = somefunction;
this.f();
By the way, the this point in javascript function call chain is not inherited. So if within a function A, the this points to instance Obj1, then calling function b from function A, within the function b, the this pointer is the global object, instead of Obj1. If you want to set the this pointer Obj1 to be function b's this pointer, then you must first assign function b as a member of Obj1, and then calling function as its member function. This also explains why we need to assign onclick attribute to a external function and then call onclick to keep the current html element as the external function's this object.
function f(m,n) {
this.x = m;
this.y = n;
}
Then calling
var o1 = f;
Then the type of o is an object that represents the function. It is not a instance that is created by the f function.
Now let us see what happens if calling
var o2 = new f;
This time, the function serves as the construct to create a instance . The instance has two data member x, and y, whose values are not initialized. To set the data member values, calling
var o3 = new f(1, 2);
Now try to use the function in a different way as showing below
var o3 = f(2, 3);
This time, the function f is not used as a constructor, instead it is just a normal javascript method call, inside the function f, this pointer points to the window object of the current html page, and it just sets two new data members to the window object.
Another thing unique in javascript is, although any object instance can add new data members by just calling assigning operation as below
this.x = somevalue;
It can not do so to directly call a javascript funtion on an instance object. Instead, it must first assign the function to the instance's member before calling the function on it.
this.f = somefunction;
this.f();
By the way, the this point in javascript function call chain is not inherited. So if within a function A, the this points to instance Obj1, then calling function b from function A, within the function b, the this pointer is the global object, instead of Obj1. If you want to set the this pointer Obj1 to be function b's this pointer, then you must first assign function b as a member of Obj1, and then calling function as its member function. This also explains why we need to assign onclick attribute to a external function and then call onclick to keep the current html element as the external function's this object.
Friday, March 25, 2011
Relative or absolute path in URL
When a javascript method or html link refers to an element in the url, if the relative path is used, the path base is the current displaying html page. As a result, the target location will be different depending on the current displaying page's location. If the javascript method or html page refers to an element using absolute path format, then it is always based on the root folder of the virtual directory, and the target location is irrelevant to the current displaying page's location.
The format of absolute path starts with a single forward slash, avoiding using a back slash since some clients may not support it.
The format of relative path starts without any slash. If the relative path starts with '../', it will go to the parent folder of the current displaying page. However, if it already reaches the root folder of the virtual directory, then the root folder will be used to locate the target item.
Jonathan
The format of absolute path starts with a single forward slash, avoiding using a back slash since some clients may not support it.
The format of relative path starts without any slash. If the relative path starts with '../', it will go to the parent folder of the current displaying page. However, if it already reaches the root folder of the virtual directory, then the root folder will be used to locate the target item.
Jonathan
Saturday, March 19, 2011
Show Dialog with onBackPressed and onPause method
onPause method in Android activity is for saving the UI state data, when onPause is called, the OS already puts the current activity in background and starts to render the target activity. So no any UI related operation (for example, showing a dialog box, etc.) should be put into onPause method.
If there is a need to do UI related operation, like prompting user to save the pending change or cancel the current operation, then those UI related operation should be put into menu handler or onBackPressed method.
If there is a need to do UI related operation, like prompting user to save the pending change or cancel the current operation, then those UI related operation should be put into menu handler or onBackPressed method.
Sunday, March 6, 2011
Showing Dialog in Android Application
First, different from other platforms, showing dialog in Android will not block the current execution. So that the code behind Dialog.show() will be executed immediately without waiting the dialog gets closed. As a result, anything that needs to be called after closing the dialog should be put into dialog's button handling method.
Second, there is not a single method that can be called to show a dialog. The simplest code to show a dialog box is as follows
Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("my title");
alertDialog.setMessage("my message.");
alertDialog.show();
Third, if you do not want user to cancel the dialog by selecting the back key, then call the following method before alertDialog.show();
alertDialog.setCancelable(false);
Finally, if you want user to select a yes/no option by clicking a button in the dialog box, two other methods should be called to set these button's text and callback methods. A full functioning dialog is showing below:
AlertDialog.Builder ad = new AlertDialog.Builder(myActivity.this);
ad.setTitle("my title");
ad.setMessage("my message");
ad.setPositiveButton("Yes", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
// do yes operation
}
});
ad.setNegativeButton("No", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
// do no operation
}
});
ad.setCancelable(true);
ad.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// do cancel operation
}
});
ad.show();
Note if you show two dialogs (that is, calling Dialog.show()) within a single method, then the second dialog will show on the top of the first one. Only after the second dialog gets dismissed, then the first one will become the active dialog.
Jonathan
Second, there is not a single method that can be called to show a dialog. The simplest code to show a dialog box is as follows
Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("my title");
alertDialog.setMessage("my message.");
alertDialog.show();
Third, if you do not want user to cancel the dialog by selecting the back key, then call the following method before alertDialog.show();
alertDialog.setCancelable(false);
Finally, if you want user to select a yes/no option by clicking a button in the dialog box, two other methods should be called to set these button's text and callback methods. A full functioning dialog is showing below:
AlertDialog.Builder ad = new AlertDialog.Builder(myActivity.this);
ad.setTitle("my title");
ad.setMessage("my message");
ad.setPositiveButton("Yes", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
// do yes operation
}
});
ad.setNegativeButton("No", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
// do no operation
}
});
ad.setCancelable(true);
ad.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// do cancel operation
}
});
ad.show();
Note if you show two dialogs (that is, calling Dialog.show()) within a single method, then the second dialog will show on the top of the first one. Only after the second dialog gets dismissed, then the first one will become the active dialog.
Jonathan
ListView, ListAdapter, ListActivity in Android
ListView is derived from View class, so it can be used by Activity in the similar way as EditText or Button View. ListView is also derived from ViewGroup, so it has the ability to contain a list of view for the list item.
In order to show the list view, the only method that needs to be called is
setAdapter( ListAdapter adapter). The ListAdatper parameter provides the views for showing each list item.
ListAdapter class mentoned in setAdapter method is responsible to render list item. Its first responsibility is holding the data of list item, which is passed as paramter to its constructor. The second responsibility is returning a view for each item when asked by ListView classm, the layout resource of the item view is passed to it as another paramter in its constructor.
Now let us take a look at ListActivity, basically, it is a activity that has a listView in it. In order to show a list items, the only method needs to be called is setListAdapter(adapter) in the overrided onCreate method. The following is the simple code to show a string array in listActivity, it does not even require to define any layout resources.
public class MyListActivity extends ListActivity {
@Override
public void onCreate(Bundle data) {
super.onCreate(data);
ArrayList myString = new ArrayList();
myString.add("string1");
myString.add("string2");
myString.add("string3");
myString.add("string4");
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, myString);
setListAdapter(adapter);
}
}
Jonathan
In order to show the list view, the only method that needs to be called is
setAdapter( ListAdapter adapter). The ListAdatper parameter provides the views for showing each list item.
ListAdapter class mentoned in setAdapter method is responsible to render list item. Its first responsibility is holding the data of list item, which is passed as paramter to its constructor. The second responsibility is returning a view for each item when asked by ListView classm, the layout resource of the item view is passed to it as another paramter in its constructor.
Now let us take a look at ListActivity, basically, it is a activity that has a listView in it. In order to show a list items, the only method needs to be called is setListAdapter(adapter) in the overrided onCreate method. The following is the simple code to show a string array in listActivity, it does not even require to define any layout resources.
public class MyListActivity extends ListActivity {
@Override
public void onCreate(Bundle data) {
super.onCreate(data);
ArrayList
myString.add("string1");
myString.add("string2");
myString.add("string3");
myString.add("string4");
ArrayAdapter adapter = new ArrayAdapter
setListAdapter(adapter);
}
}
Jonathan
Fix Link Error When Viewing Android Offline Document
After installing Android offline document for Android SDK API 11 and opening index.html from Windows File explorer, clicking any link (like Reference or SDK) on the index page will cause an error. The reason is the link automatically adds the root driver again in the new address, so the target address becomes an invalid one as showing below.
C:\C:\Program Files (x86)\Android\android-sdk-windows\docs\reference\android\text\util\package-summary.html
A quick fix is creating a virtual directory in IIS and point it to the android document folder, and then open index.html from the virtual directory as below, then everything works as supposed.
http://localhost/androiddoc/index.html
Jonathan
C:\C:\Program Files (x86)\Android\android-sdk-windows\docs\reference\android\text\util\package-summary.html
A quick fix is creating a virtual directory in IIS and point it to the android document folder, and then open index.html from the virtual directory as below, then everything works as supposed.
http://localhost/androiddoc/index.html
Jonathan
Tuesday, March 1, 2011
Use FLAG_ACTIVITY_NEW_TASK flag when starting activity
When calling startActivity, the new activity will live in the same screen stack (context) as the caller. Sometime, the caller may not have an activity context, for instance, starting an activity from Broadcastreceive.onReceive() method, or starting an activity from a service. In these cases, call startActivity will cause an exception of "Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK", since the new activity does not have a context to live in.
To fix the issue, setting FLAG_ACTIVITY_NEW_TASK to the intent as follows, then a new context will be created for the new activity.
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jonathan
To fix the issue, setting FLAG_ACTIVITY_NEW_TASK to the intent as follows, then a new context will be created for the new activity.
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jonathan
Sunday, February 27, 2011
Difference between pressing HOME and Back key for Android activity
After you start an activity, if HOME key is pressed, then the current activity is stopped and its task goes into the background. The system retains the state of the activity - i.e. onSaveInstanceState will be called. If the user later resumes the task by selecting the launcher icon that began the task again, the task comes to the foreground and resumes the activity at the top of the stack.
However, if BACK key is pressed, the current activity is popped from the stack and destroyed. The assmuption is the activity is done and will not be used again. So the system does not retain the activity's state - i.e. onSaveInstanceState will not be called.
Jonathan
However, if BACK key is pressed, the current activity is popped from the stack and destroyed. The assmuption is the activity is done and will not be used again. So the system does not retain the activity's state - i.e. onSaveInstanceState will not be called.
Jonathan
Automatically format the java source file for Android Eclipse
Eclipse java project, Ctrl + Shift + F can be used to automatically format the source file.
You can also first select the lines in source file and then use Ctrl+I to only format the selected lines.
Another option is automatically formatting the source file when saving the file. To configure this, go to Windows->Preference->Java->Editor->Save Action, and enable the option of "Format All Lines".
This will save a lot of time to manually format the code and also make it more readable.
Other useful short cut keys:
Ctrl+Shift+E: showing the list of all opened editor,
Ctrl+Shift+F6: navigateing to previous editor
Ctrl+F6: navigating to next editor
Ctrl+/: comment and uncomment all selected lines.
Jonathan
You can also first select the lines in source file and then use Ctrl+I to only format the selected lines.
Another option is automatically formatting the source file when saving the file. To configure this, go to Windows->Preference->Java->Editor->Save Action, and enable the option of "Format All Lines".
This will save a lot of time to manually format the code and also make it more readable.
Other useful short cut keys:
Ctrl+Shift+E: showing the list of all opened editor,
Ctrl+Shift+F6: navigateing to previous editor
Ctrl+F6: navigating to next editor
Ctrl+/: comment and uncomment all selected lines.
Jonathan
Wednesday, February 23, 2011
Andoid Activity Life Cycle - onSaveInstanceState and onRestoreInstanceState
onSaveInstanceState and onRestoreInstanceState are two methods involved in Android Activity life cycle. There are several factors deciding when they will be called.
First, the data bundle mananged by these two methods are only valid within a single application running session. So if the application exits and restarts, then OnRestoreInstance will not be called, since no data are available. For the same reason, null is passed as parameter for onCreate method when onCreated is called in the first time.
MyActivity onCreate (null)
MyActivity onStart
MyActivity onResume
Second, onSaveInstanceState is always called before onPause method when starting to deactivate or close the Activity.
MyActivity onSaveInstanceState
MyActivity onPause
Third, in the same application session, onRestoreInstance will only be called if onDestroy has been called before it. Or in other word, onCreate is called before it.
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
MyActivity onCreate (obj)
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
A sample of full cycle looks as below:
MyActivity onCreate
MyActivity onStart
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
MyActivity onCreate
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
Usually, onRestoreInstanceState will not be called since most of time the activity is still alive after it is stopped, as shown below:
MyActivity onCreate
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onRestart
MyActivity onStart
MyActivity onResume
There are two ways to force the activity to be destroyed immediately.
The first way is changing the orientation of the simulator, it will force all activities to be destroyed and then created again. Another way is enabling Immediately destroy activities from dev tool's development settings page.
Jonathan
First, the data bundle mananged by these two methods are only valid within a single application running session. So if the application exits and restarts, then OnRestoreInstance will not be called, since no data are available. For the same reason, null is passed as parameter for onCreate method when onCreated is called in the first time.
MyActivity onCreate (null)
MyActivity onStart
MyActivity onResume
Second, onSaveInstanceState is always called before onPause method when starting to deactivate or close the Activity.
MyActivity onSaveInstanceState
MyActivity onPause
Third, in the same application session, onRestoreInstance will only be called if onDestroy has been called before it. Or in other word, onCreate is called before it.
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
MyActivity onCreate (obj)
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
A sample of full cycle looks as below:
MyActivity onCreate
MyActivity onStart
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
MyActivity onCreate
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onDestroy
Usually, onRestoreInstanceState will not be called since most of time the activity is still alive after it is stopped, as shown below:
MyActivity onCreate
MyActivity onStart
MyActivity onRestoreInstanceState
MyActivity onResume
MyActivity onSaveInstanceState
MyActivity onPause
MyActivity onStop
MyActivity onRestart
MyActivity onStart
MyActivity onResume
There are two ways to force the activity to be destroyed immediately.
The first way is changing the orientation of the simulator, it will force all activities to be destroyed and then created again. Another way is enabling Immediately destroy activities from dev tool's development settings page.
Jonathan
Tuesday, February 22, 2011
How to change the orientation on Android simulator
During the testing of event handler of onConfigurationChanged, you will need to change the simulator's orientation.
Actually, it is quite simple to do so, first setting the current active window to Android simlator, and then press the key of Ctrl+F11 on your desktop computer (not the android simulator's key pad).
Jonathan
Actually, it is quite simple to do so, first setting the current active window to Android simlator, and then press the key of Ctrl+F11 on your desktop computer (not the android simulator's key pad).
Jonathan
Monday, February 21, 2011
Install Windows Phone 7 Developing Tool on Windows Server 2008
By default, only Vista and Windows 7 are supported for the Windows Phone 7 development tools. In order to install it on Windows Server 2008, the following steps are required:
1. download Windows Phone Developer tool from
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&displaylang=en
2. extrace the downloaded file by running a console command: vm_web.exe /x
3. Edit extracted file baseline.dat, by looking for section named [gencomp7788]
Changing the value InstallOnLHS from 1 to 0
Changing the value InstallOnWin7Server from 1 to 0
4. Save the udpated baseline.dat
5. Run setup.exe /web
6. Download and install Windows phone developer Tool Janunary 2011 Update from
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=49b9d0c5-6597-4313-912a-f0cca9c7d277&displaylang=en
Jonathan
1. download Windows Phone Developer tool from
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&displaylang=en
2. extrace the downloaded file by running a console command: vm_web.exe /x
3. Edit extracted file baseline.dat, by looking for section named [gencomp7788]
Changing the value InstallOnLHS from 1 to 0
Changing the value InstallOnWin7Server from 1 to 0
4. Save the udpated baseline.dat
5. Run setup.exe /web
6. Download and install Windows phone developer Tool Janunary 2011 Update from
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=49b9d0c5-6597-4313-912a-f0cca9c7d277&displaylang=en
Jonathan
Subclass Application class for Android project
In order to handle several system events, like low memory, configuration change, you will need to subclass from Android Application class. Note that only creating a derived Application class and adding it into the project are not enough. You also need to update the project's manifest file to specify the derived class full name in Application node's name attribute, as shown below:
MyApplication sub class:
public class MyApplication extends Application {
public static final String MyAppTag = "MyAppTag";
@Override
public final void onCreate() {
Log.v(MyAppTag, "MyAppliation onCreate");
super.onCreate();
}
}
Updated AndroidManifest.xml:
android:label="@string/app_name"
android:name="MyApplication"
android:description="@string/app_desc"
Jonathan
MyApplication sub class:
public class MyApplication extends Application {
public static final String MyAppTag = "MyAppTag";
@Override
public final void onCreate() {
Log.v(MyAppTag, "MyAppliation onCreate");
super.onCreate();
}
}
Updated AndroidManifest.xml:
android:label="@string/app_name"
android:name="MyApplication"
android:description="@string/app_desc"
Jonathan
Sunday, February 20, 2011
Write and view debug output from Eclipse for Android
Sooner or later, you will need the debug output to help you in Android development. The old System.out.println still works, but you need to view the output from Android LogCat instead of Eclipse Console window. To open and view the output of LogCat, open Eclipse menu of Window->Show View->Others->Android->LogCat.
However, although the debug output is available in LogCat, there are quite a lot of other debug output, which really makes it difficult to find the log you are interested. To handle the issue, Log class should be used to write the debug output, since Log class provides a way to specify a log tag for each log entry, and you can filter the entries in LogCat by log tag.
public class myActivity extends Activity {
public static final String MyActivityTag = "MyActivityTag";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.v(MyActivityTag, "MyActivity onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Note you can add multiple log filter by clicking the '+' icon in Log Cat view. For each log filter, a separate log output tab page will be created for showing the log entries belonging to this log tag.
Jonathan
However, although the debug output is available in LogCat, there are quite a lot of other debug output, which really makes it difficult to find the log you are interested. To handle the issue, Log class should be used to write the debug output, since Log class provides a way to specify a log tag for each log entry, and you can filter the entries in LogCat by log tag.
public class myActivity extends Activity {
public static final String MyActivityTag = "MyActivityTag";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.v(MyActivityTag, "MyActivity onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
Note you can add multiple log filter by clicking the '+' icon in Log Cat view. For each log filter, a separate log output tab page will be created for showing the log entries belonging to this log tag.
Jonathan
Saturday, February 19, 2011
Reference Android Resource
There are two way to refer a Android resource - from code and from xml resource file.
To refer resource in code, the format is R.Calss.ResourceName. The following are some usage sample.
setcontentview(R.layout.main)
Resources myResources = getResources();
CharSequence styledText = myResources.getText(R.string.stop_message);
To refer resource as attribute in xml, the format is
"@[packagename:]Class/ResourceName" as showing in the following example:
android:text="@string/stop_message" android:textColor="@color/opaque_blue" />
Usually, you do not need to include the package name, unless you need to refer a system defined resource. The following sample referrs to system color darker_gray
android:textColor="@android:color/darker_gray" />
In rare occasion, you may also see a ? in the format as following sample
android:textColor="?android:textColor"
? means using the current textColor defined for the view, so the actual color can only be decided at runtime.
Jonathan
To refer resource in code, the format is R.Calss.ResourceName. The following are some usage sample.
setcontentview(R.layout.main)
Resources myResources = getResources();
CharSequence styledText = myResources.getText(R.string.stop_message);
To refer resource as attribute in xml, the format is
"@[packagename:]Class/ResourceName" as showing in the following example:
Usually, you do not need to include the package name, unless you need to refer a system defined resource. The following sample referrs to system color darker_gray
In rare occasion, you may also see a ? in the format as following sample
android:textColor="?android:textColor"
? means using the current textColor defined for the view, so the actual color can only be decided at runtime.
Jonathan
Android Resource ID Format
When defining resource for Android, the format of resource id attribute looks like android:id="@+id/item01"
The '@' at the beginning of the string is just a delimiter, and indicates that the following string is an ID resource.
The '+' means that this is a new resource id that must be created and added to the resource R file. However if the same resource ID are defined more than once, only one ID is included in R file.
The 'id/item01' is the class and data member name included in the generated R class. The resource can be referred as R.id.item01. The class name is required, so just define 'item01' is invalid. If the resource id is defined as android:id="@+idd/ddd/item01", then the generated R file only includes R.idd.ddd as the reource id.
Do not mix resource id with resource name. Resource name is used to identify a resource. Some resource includes a list of items, like menu items in a menu resource, so resource id can be used to identify a particular item in the list.
Jonathan
The '@' at the beginning of the string is just a delimiter, and indicates that the following string is an ID resource.
The '+' means that this is a new resource id that must be created and added to the resource R file. However if the same resource ID are defined more than once, only one ID is included in R file.
The 'id/item01' is the class and data member name included in the generated R class. The resource can be referred as R.id.item01. The class name is required, so just define 'item01' is invalid. If the resource id is defined as android:id="@+idd/ddd/item01", then the generated R file only includes R.idd.ddd as the reource id.
Do not mix resource id with resource name. Resource name is used to identify a resource. Some resource includes a list of items, like menu items in a menu resource, so resource id can be used to identify a particular item in the list.
Jonathan
Friday, January 28, 2011
DependencyProperty in SilverLight/WPF
Unlike usual .Net property, DependencyProperty is defined as static member for a class. The dependencyProperty is not used to store the data as instance members, instead it is used to indicate that the class understands the defined depenency property, so knows how to use this DependencyProperty.
Usually, the class also defines the get/set wrap accessors for the DependencyProperty, they are instance members, since they use the DependencyProperty as key to read and set the data from the hashtable that stores all dependency values.
Note once a DependencyProperty is defined in a class, the value for this property can be set/get to any classes that derived from DependencyObject, not only the class defines it. For example Grid.ColumnProperty in Grid class can be set to a TextField instance. However, only Grid class knows how to apply this property when laying out the TextField. The TextField just stores the value into its DependencyProperty hash table, and never knows what this property really means. In this sense, the DependencyProperty is also called as AttachedProperty.
Jonathan
Usually, the class also defines the get/set wrap accessors for the DependencyProperty, they are instance members, since they use the DependencyProperty as key to read and set the data from the hashtable that stores all dependency values.
Note once a DependencyProperty is defined in a class, the value for this property can be set/get to any classes that derived from DependencyObject, not only the class defines it. For example Grid.ColumnProperty in Grid class can be set to a TextField instance. However, only Grid class knows how to apply this property when laying out the TextField. The TextField just stores the value into its DependencyProperty hash table, and never knows what this property really means. In this sense, the DependencyProperty is also called as AttachedProperty.
Jonathan
Sunday, January 2, 2011
adb.exe in Android SDK not installed on Windows Server 2008 (64 bit)
When installing Android SDK to Windows Server 2008 (64 bit), adb.exe does not get installed in platform-tools folder, it seems Windows server 2008 is not a supported platform, although it is unlikely there is any difference between Win Server 2008 (64 bit) and Windows 7 (64 bit) in term of eclipse for android support.
A workaround is copying the whole platform-tools folder from Windows 7 to Windows server 2008. And then set the Android sdk location again from Eclipse Windows->Preference menu, and all function works just fine.
Jonathan
A workaround is copying the whole platform-tools folder from Windows 7 to Windows server 2008. And then set the Android sdk location again from Eclipse Windows->Preference menu, and all function works just fine.
Jonathan
Subscribe to:
Posts (Atom)