1. Introduction
This is my first tutorial.
This tutorial isnt meant to be for whole mission.
Just part of it.
2. Getting the source code
Its assumed you got m*******.***s code and understand perls
code or at least syntax which is very similar to c or php.
3. Searching for exploits in code
Ive extracted particularly validkey function because rest of code
is doing pretty much nothing, if you cant have other functions.
You should have noticed that by now.
4. Understanding the code
If first argument($_[0]) isnt in range of alphanumerical
chars it will return 0 value or outside the function:
"You have entered an invalid id."
As you can see it uses regexp.
Splits every character in first argument($_[0]) and total,counter = 0
While idchars array is defined (true),
total of ascii code from given character plus total itself * counter
will give $total and counter goes up by 1.
If total is in range from 925559-927901 then we have valid id
anything else outside the range will return 0 (invalid key).
5. Coding
There are to ways two do this (in general):
Inputting different keys until we get right value which is range or
brute-force function until we get list of valid keys.
Pseudo code:
CODE :
__________________________________________________________________________
split keys
for i = 0 to len(keys)
do
key = keys[i]
validkey+= (ord(key[i]) + (total*i))
echo validkey
if valid key in range 925559-927901
then echo "valid key"
__________________________________________________________________________
6. Links
Regular Expressions
http://www.php.net/
http://www.python.org/download/
http://www.perl.com/download.csp
http://en.wikipedia.org/wiki/Regular_expression
PM or Email me with your codes or questions.
Thats pretty much all.
Showing posts with label Internet. Show all posts
Showing posts with label Internet. Show all posts
Tuesday, February 9, 2010
Realistic 14 - Valid Key
1. Introduction
This is my first tutorial.
This tutorial isnt meant to be for whole mission.
Just part of it.
2. Getting the source code
Its assumed you got m*******.***s code and understand perls
code or at least syntax which is very similar to c or php.
3. Searching for exploits in code
Ive extracted particularly validkey function because rest of code
is doing pretty much nothing, if you cant have other functions.
You should have noticed that by now.
4. Understanding the code
If first argument($_[0]) isnt in range of alphanumerical
chars it will return 0 value or outside the function:
"You have entered an invalid id."
As you can see it uses regexp.
Splits every character in first argument($_[0]) and total,counter = 0
While idchars array is defined (true),
total of ascii code from given character plus total itself * counter
will give $total and counter goes up by 1.
If total is in range from 925559-927901 then we have valid id
anything else outside the range will return 0 (invalid key).
5. Coding
There are to ways two do this (in general):
Inputting different keys until we get right value which is range or
brute-force function until we get list of valid keys.
Pseudo code:
CODE :
__________________________________________________________________________
split keys
for i = 0 to len(keys)
do
key = keys[i]
validkey+= (ord(key[i]) + (total*i))
echo validkey
if valid key in range 925559-927901
then echo "valid key"
__________________________________________________________________________
6. Links
Regular Expressions
http://www.php.net/
http://www.python.org/download/
http://www.perl.com/download.csp
http://en.wikipedia.org/wiki/Regular_expression
PM or Email me with your codes or questions.
Thats pretty much all.
This is my first tutorial.
This tutorial isnt meant to be for whole mission.
Just part of it.
2. Getting the source code
Its assumed you got m*******.***s code and understand perls
code or at least syntax which is very similar to c or php.
3. Searching for exploits in code
Ive extracted particularly validkey function because rest of code
is doing pretty much nothing, if you cant have other functions.
You should have noticed that by now.
4. Understanding the code
If first argument($_[0]) isnt in range of alphanumerical
chars it will return 0 value or outside the function:
"You have entered an invalid id."
As you can see it uses regexp.
Splits every character in first argument($_[0]) and total,counter = 0
While idchars array is defined (true),
total of ascii code from given character plus total itself * counter
will give $total and counter goes up by 1.
If total is in range from 925559-927901 then we have valid id
anything else outside the range will return 0 (invalid key).
5. Coding
There are to ways two do this (in general):
Inputting different keys until we get right value which is range or
brute-force function until we get list of valid keys.
Pseudo code:
CODE :
__________________________________________________________________________
split keys
for i = 0 to len(keys)
do
key = keys[i]
validkey+= (ord(key[i]) + (total*i))
echo validkey
if valid key in range 925559-927901
then echo "valid key"
__________________________________________________________________________
6. Links
Regular Expressions
http://www.php.net/
http://www.python.org/download/
http://www.perl.com/download.csp
http://en.wikipedia.org/wiki/Regular_expression
PM or Email me with your codes or questions.
Thats pretty much all.
Writing Your Own Python Modules
Extending the Python Language with your own Modules
One of the best bits about Python is the extensive catalogue of modules that are around, and free, to extend the power and functionality of the language. Sometimes, however, it is necessary to create your own - perhaps because a particular feature isn't available in the standard build, perhaps a new technology has arrived that you wish to write an API for, or perhaps you are writing a large application where the breaking up of code is necessary for it to remain flexible and unbloated. Whatever your reasoning, this article serves as a basic introduction to module creation in Python. It covers both procedural and Object Orientated programming, but will not go into detailed specifics of either. However, it will give enough information for you to be able to begin developing your own "add-ons" to the Python language.
I'm using Python 2.6 so there will be slight differences if you are using another version.
Brief Overview of Modules in Python
Modules in Python are imported using the "import" statement.
CODE :
__________________________________________________________________________
import re
__________________________________________________________________________
That, for example, imports "re" - the regex module - into the document. The functions and classes belonging to "re" can be accessed like so:
CODE :
__________________________________________________________________________
import re
re.function(....)
__________________________________________________________________________
Modules on my system (Linux Xubuntu) are stored in /usr/lib/python2.6/
It'll be different on Windows - obviously - and may be on Mac and other Linux distros. You'll have to do some searching. On a *nix system, using this command should help you locate them:
CODE :
__________________________________________________________________________
locate urllib2
__________________________________________________________________________
However you don't have to stick all your modules in there, if the python interpretter can't find your module there, it'll look in the current working directory.
Modules have to end with .py too.
Your First Module
First I'm going to create two files: "firstmod.py" - which will contain the actual module - and "test.py" - with which we will test it (this could also be replaced by the Python console).
CODE :
__________________________________________________________________________
# firstmod.py
def doSomething(a,b):
c = a + b + 5
return c
__________________________________________________________________________
CODE :
__________________________________________________________________________
# test.py
import firstmod
print firstmod.doSomething(5,6)
__________________________________________________________________________
When we execute test.py, we get 16.
The code is pretty self explanatory. Now I'm going to do something a little different.
CODE :
__________________________________________________________________________
#test.py
from firstmod import doSomething
print doSomething(4,9)
__________________________________________________________________________
This time, instead of importing the entire module (which, admittedly, in this case is still only the one function), we are just importing that doSomething function. However, there's another difference. We're not accessing that function through the module itself but instead as we would any other function that we have created. That can be useful if you only want to access the one function, and don't want to have to type out a long module name each time you want to use it.
Another way of using the "from ... import ..." statement is with the wildcard '*'. Now you should know that that means everything, and that's exactly what it does. Import everything. In most cases you shouldn't do that, but there are cases when it is useful - especially when doing GUI programming, should you want to.
CODE :
__________________________________________________________________________
#test.py
from firstmod import *
print doSomething(2,6)
__________________________________________________________________________
See? Pretty simple.
[h3]Initialisation[/h3]
You may, for some reason, want to execute a few lines of code as soon as your module is imported. What for, I don't know, but perhaps there's an application. To do this, well.. just write that code in there.
CODE :
__________________________________________________________________________
# firstmod.py
def doSomething(a,b):
c = a + b + 5
return c
print "Initialised."
a = 5
__________________________________________________________________________
Okay, so I've made it print out "Initialised" and have set the variable "a" to 5. Now what does this look like when I import it?
I'll show you the output from the Python console.
CODE :
__________________________________________________________________________
>>> import firstmod
Initialised.
>>> print firstmod.a
5
>>> print a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
__________________________________________________________________________
That's pretty important to note. When you set a global variable in a module as I did above, you can access that variable as you would a function.
As expected, it works the same as functions when specifically imported:
CODE :
__________________________________________________________________________
>>> from firstmod import *
Initialised.
>>> print a
5
__________________________________________________________________________
However, here's a little quirk:
CODE :
__________________________________________________________________________
>>> from firstmod import doSomething
Initialised.
>>> print a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'a' is not defined
>>> print firstmod.a
Traceback (most recent call last):
File "", line 1, in
NameError: name 'firstmod' is not defined
__________________________________________________________________________
Hopefully those output snippets will help you understand how things work, I think that they explain better than I could, anyway.
[h3]Documentation[/h3]
Presumably at some point in your Python programming lives you will have used the help function. What you may not know is that the documentation for each module is in fact built in to the module.
Here's some code that will explain how it works.
CODE :
__________________________________________________________________________
# firstmod.py
"""This is an introduction to the firstmod module. It tells the user how to use the module as a whole, may give code snippets and generally give an idea of what the module does and how it does it. This can, and nearly always does, run over multiple lines."""
def doSomething(a,b):
"""This explains what this particular module does, so for example, in this circumstance I might say:
doSomething returns the sum of the two arguments with 5 added on."""
c = a + b + 5
return c
__________________________________________________________________________
Now try importing your module in the Python console, and typing "help(firstmod)".
[h3]Object Orientated[/h3]
Object Orientated programming is a tricky subject and can take a while to grasp completely. It's something that I like, but am wary of, and would advise anyone to read a lot about it before just jumping in.
I think the best way to teach this bit would be to actually create a working module - so that's what we'll do. We're going to write a 'toggle' variable: a variable with two specific positions and a function that switches between them. The best example is "True" or "False". Yep, they already have the boolean variable. Yep, you probably will never use this (though I've actually used it occasionally). Yep, it's pretty simple and a good learning script. So let's get started.
You can look at the full, finished code here: http://pastebin.com/m64220b4b
We won't be writing that much but feel free to add to the module if you want.
First of all I'm going to create a single file, "toggle.py". I will use the Python console for importing the module, etc.
Inside that, we'll have the class "toggle". Let's write some code.
CODE :
__________________________________________________________________________
# toggle.py
"""Toggle variable module"""
class toggle(object):
"""Toggle object with 2 possible values"""
def __init__(self, first, second):
"""This is executed as soon as the class is loaded"""
self.statements = first,second
self.position = 0
__________________________________________________________________________
Right, I'm going to stop there and explain a little. From now on, however, we'll be adding code to that class (not function), unless I state otherwise.
If we were to import this code and use it, we'd do it like this:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
__________________________________________________________________________
The self in self.statements and self.position refers to the class itself. I won't explain it in detail because that'd involve basically explaining OOP, which would take another article. The self.statements variable is a tuple. It is assigned the variables passed to the __init__ function.
Okay, let's give this some functionality - we're going to make the object return a value when printed. Try this:
CODE :
__________________________________________________________________________
import toggle
t = toggle.toggle()
print t
__________________________________________________________________________
Now wouldn't it be nicer if it returned the current value then, rather than some weird value? Python is great in the way it lets you manipulate the language like that, here's how we'd do it:
CODE :
__________________________________________________________________________
# remember, we're adding a new function to the class here
def __str__(self):
"""Returns the current value"""
return str(self.statements[self.position])
__________________________________________________________________________
Now try the previous code and see what you get. Great, eh?
Currently though, you can't change the value. I'm going to introduce a toggle() function now.
CODE :
__________________________________________________________________________
def toggle(self):
"""Switch value, returns new value"""
if self.position == 0:
self.position = 1
else:
self.position = 0
return self.statements[self.position]
__________________________________________________________________________
Pretty self explanatory really. Let's try using it now:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
>>> print t
option1
>>> t.toggle()
'option2'
>>> print t
option2
__________________________________________________________________________
[h3]Conclusion[/h3]
There we have it. That's your first basic module. There's a lot more you can do too and I encourage you to read up more on the subject. Writing modules is great fun, especially if you know Perl or another scripting language, and can port some modules over.
If you want to try out your skills writing modules, why not consider writing an IRC bot module? Or a noughts and crosses game, perhaps? There are plenty of applications.
Here's an old module I wrote for writing IRC bots. It isn't complete and it is probably pretty poorly coded in parts - I haven't looked at it for a while now. I'm not saying that it's perfect at all, but why don't you fix some problems it has? It definitely needs some regexs in there - message parsing has been done by hand :/
http://pastebin.com/m4e121ebf
Good luck, thanks for reading and have fun!
If there are any errors in the article, please leave a comment (or PM me if the comments system is down). Feel free to leave your opinions. :)
~thedotmaster
One of the best bits about Python is the extensive catalogue of modules that are around, and free, to extend the power and functionality of the language. Sometimes, however, it is necessary to create your own - perhaps because a particular feature isn't available in the standard build, perhaps a new technology has arrived that you wish to write an API for, or perhaps you are writing a large application where the breaking up of code is necessary for it to remain flexible and unbloated. Whatever your reasoning, this article serves as a basic introduction to module creation in Python. It covers both procedural and Object Orientated programming, but will not go into detailed specifics of either. However, it will give enough information for you to be able to begin developing your own "add-ons" to the Python language.
I'm using Python 2.6 so there will be slight differences if you are using another version.
Brief Overview of Modules in Python
Modules in Python are imported using the "import" statement.
CODE :
__________________________________________________________________________
import re
__________________________________________________________________________
That, for example, imports "re" - the regex module - into the document. The functions and classes belonging to "re" can be accessed like so:
CODE :
__________________________________________________________________________
import re
re.function(....)
__________________________________________________________________________
Modules on my system (Linux Xubuntu) are stored in /usr/lib/python2.6/
It'll be different on Windows - obviously - and may be on Mac and other Linux distros. You'll have to do some searching. On a *nix system, using this command should help you locate them:
CODE :
__________________________________________________________________________
locate urllib2
__________________________________________________________________________
However you don't have to stick all your modules in there, if the python interpretter can't find your module there, it'll look in the current working directory.
Modules have to end with .py too.
Your First Module
First I'm going to create two files: "firstmod.py" - which will contain the actual module - and "test.py" - with which we will test it (this could also be replaced by the Python console).
CODE :
__________________________________________________________________________
# firstmod.py
def doSomething(a,b):
c = a + b + 5
return c
__________________________________________________________________________
CODE :
__________________________________________________________________________
# test.py
import firstmod
print firstmod.doSomething(5,6)
__________________________________________________________________________
When we execute test.py, we get 16.
The code is pretty self explanatory. Now I'm going to do something a little different.
CODE :
__________________________________________________________________________
#test.py
from firstmod import doSomething
print doSomething(4,9)
__________________________________________________________________________
This time, instead of importing the entire module (which, admittedly, in this case is still only the one function), we are just importing that doSomething function. However, there's another difference. We're not accessing that function through the module itself but instead as we would any other function that we have created. That can be useful if you only want to access the one function, and don't want to have to type out a long module name each time you want to use it.
Another way of using the "from ... import ..." statement is with the wildcard '*'. Now you should know that that means everything, and that's exactly what it does. Import everything. In most cases you shouldn't do that, but there are cases when it is useful - especially when doing GUI programming, should you want to.
CODE :
__________________________________________________________________________
#test.py
from firstmod import *
print doSomething(2,6)
__________________________________________________________________________
See? Pretty simple.
[h3]Initialisation[/h3]
You may, for some reason, want to execute a few lines of code as soon as your module is imported. What for, I don't know, but perhaps there's an application. To do this, well.. just write that code in there.
CODE :
__________________________________________________________________________
# firstmod.py
def doSomething(a,b):
c = a + b + 5
return c
print "Initialised."
a = 5
__________________________________________________________________________
Okay, so I've made it print out "Initialised" and have set the variable "a" to 5. Now what does this look like when I import it?
I'll show you the output from the Python console.
CODE :
__________________________________________________________________________
>>> import firstmod
Initialised.
>>> print firstmod.a
5
>>> print a
Traceback (most recent call last):
File "
NameError: name 'a' is not defined
__________________________________________________________________________
That's pretty important to note. When you set a global variable in a module as I did above, you can access that variable as you would a function.
As expected, it works the same as functions when specifically imported:
CODE :
__________________________________________________________________________
>>> from firstmod import *
Initialised.
>>> print a
5
__________________________________________________________________________
However, here's a little quirk:
CODE :
__________________________________________________________________________
>>> from firstmod import doSomething
Initialised.
>>> print a
Traceback (most recent call last):
File "
NameError: name 'a' is not defined
>>> print firstmod.a
Traceback (most recent call last):
File "
NameError: name 'firstmod' is not defined
__________________________________________________________________________
Hopefully those output snippets will help you understand how things work, I think that they explain better than I could, anyway.
[h3]Documentation[/h3]
Presumably at some point in your Python programming lives you will have used the help function. What you may not know is that the documentation for each module is in fact built in to the module.
Here's some code that will explain how it works.
CODE :
__________________________________________________________________________
# firstmod.py
"""This is an introduction to the firstmod module. It tells the user how to use the module as a whole, may give code snippets and generally give an idea of what the module does and how it does it. This can, and nearly always does, run over multiple lines."""
def doSomething(a,b):
"""This explains what this particular module does, so for example, in this circumstance I might say:
doSomething returns the sum of the two arguments with 5 added on."""
c = a + b + 5
return c
__________________________________________________________________________
Now try importing your module in the Python console, and typing "help(firstmod)".
[h3]Object Orientated[/h3]
Object Orientated programming is a tricky subject and can take a while to grasp completely. It's something that I like, but am wary of, and would advise anyone to read a lot about it before just jumping in.
I think the best way to teach this bit would be to actually create a working module - so that's what we'll do. We're going to write a 'toggle' variable: a variable with two specific positions and a function that switches between them. The best example is "True" or "False". Yep, they already have the boolean variable. Yep, you probably will never use this (though I've actually used it occasionally). Yep, it's pretty simple and a good learning script. So let's get started.
You can look at the full, finished code here: http://pastebin.com/m64220b4b
We won't be writing that much but feel free to add to the module if you want.
First of all I'm going to create a single file, "toggle.py". I will use the Python console for importing the module, etc.
Inside that, we'll have the class "toggle". Let's write some code.
CODE :
__________________________________________________________________________
# toggle.py
"""Toggle variable module"""
class toggle(object):
"""Toggle object with 2 possible values"""
def __init__(self, first, second):
"""This is executed as soon as the class is loaded"""
self.statements = first,second
self.position = 0
__________________________________________________________________________
Right, I'm going to stop there and explain a little. From now on, however, we'll be adding code to that class (not function), unless I state otherwise.
If we were to import this code and use it, we'd do it like this:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
__________________________________________________________________________
The self in self.statements and self.position refers to the class itself. I won't explain it in detail because that'd involve basically explaining OOP, which would take another article. The self.statements variable is a tuple. It is assigned the variables passed to the __init__ function.
Okay, let's give this some functionality - we're going to make the object return a value when printed. Try this:
CODE :
__________________________________________________________________________
import toggle
t = toggle.toggle()
print t
__________________________________________________________________________
Now wouldn't it be nicer if it returned the current value then, rather than some weird value? Python is great in the way it lets you manipulate the language like that, here's how we'd do it:
CODE :
__________________________________________________________________________
# remember, we're adding a new function to the class here
def __str__(self):
"""Returns the current value"""
return str(self.statements[self.position])
__________________________________________________________________________
Now try the previous code and see what you get. Great, eh?
Currently though, you can't change the value. I'm going to introduce a toggle() function now.
CODE :
__________________________________________________________________________
def toggle(self):
"""Switch value, returns new value"""
if self.position == 0:
self.position = 1
else:
self.position = 0
return self.statements[self.position]
__________________________________________________________________________
Pretty self explanatory really. Let's try using it now:
CODE :
__________________________________________________________________________
>>> import toggle
>>> t = toggle.toggle("option1","option2")
>>> print t
option1
>>> t.toggle()
'option2'
>>> print t
option2
__________________________________________________________________________
[h3]Conclusion[/h3]
There we have it. That's your first basic module. There's a lot more you can do too and I encourage you to read up more on the subject. Writing modules is great fun, especially if you know Perl or another scripting language, and can port some modules over.
If you want to try out your skills writing modules, why not consider writing an IRC bot module? Or a noughts and crosses game, perhaps? There are plenty of applications.
Here's an old module I wrote for writing IRC bots. It isn't complete and it is probably pretty poorly coded in parts - I haven't looked at it for a while now. I'm not saying that it's perfect at all, but why don't you fix some problems it has? It definitely needs some regexs in there - message parsing has been done by hand :/
http://pastebin.com/m4e121ebf
Good luck, thanks for reading and have fun!
If there are any errors in the article, please leave a comment (or PM me if the comments system is down). Feel free to leave your opinions. :)
~thedotmaster
Label:
Internet,
programming,
python,
Scripting
An Introduction to CSRF Vulnerabilities
What is a CSRF Attack?
A CSRF attack is a form of attack in which commands are transmitted from a victim to another website without the users consent. CSRF attacks are usually invisible and rely on browser functionality (such as automatically loading images).
How is a CSRF Attack Carried Out?
CSRF attacks are embedded in an element browsers automatically react to (such as an image tag).
Lets assume that Joe has just registered with a brand new Electronic Money transfer site. When Joe wants to transfer money, he heads to www.example.com/transfer.php to send some money to his wife, Mary.
He fills out the forms for the amount of money he wants to transfer and who he wants to send the money to, and then clicks submit. The URL now looks like this:
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Joe&to=Mary&amount=2
__________________________________________________________________________
The next day, Janice, Joes angry ex-wife, also registers with the site. She decides to send $5 to her boyfriend, named Sam. She heads to www.example.com/transfer.php, fills out the forms (quite angrily), and hits submit.
She notices that the URL,
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Janice&to=Sam&amount=5
__________________________________________________________________________
does not require any authorization besides her Session cookie (which is automatically send to the web server).
Still bitter over what she thinks was an unfair settlement to her divorce with Joe, she slips on her black hat and decides to cheat Joe out of his money.
She sends a message to Joe which looks like this:
CODE :
__________________________________________________________________________
//Title: I Hate You!!!!
You are the most rotten, vile, PIG ever!!!!!
[img]www.example.com/transfer.php?from=Joe&to=Janice&amount=5000[/img]
__________________________________________________________________________
(Note that Janice used BBCode for her image tag, which example.com automatically translates into HTML.)
Later that day, Joe logs on and views the message. His browser sees the image tag and automatically follows it to
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Joe&to=Janice&amount=5000
__________________________________________________________________________
His browser then attempts to download the page and display it as an image. Because the link provided is not a valid image, the browser displays it as a broken image.
However, the server at example.com sees that Joe has visited the link, and transfers $5000 dollars to Janice.
All this happens invisibly and within seconds.
Dangers of CSRF
We now understand how a CSRF attack is performed. But, what can this attack do?
It can:
*Transfer Funds
*Log a user in/out
*Register a user
*Log data of a user
*Send a message from the victim to someone else
*Etc
The only requirement is that the server must not have a means of detecting if the user has authorized the action that a CSRF attack performs.
Prevention of CSRF Attacks
CSRF attacks can be prevented in a number of ways, but the best way to prevent them is a combination of many different methods.
CSRF attacks are much easier if an action can be performed with an HTTP GET request, but simply having only POST requests is not sufficient to prevent CSRF attacks.
One common method of preventing CSRF attacks is to have a hidden value randomly generated upon the users visit of the webpage. The advantage of this strategy is that the attacker can not predict what the token will be, and thus cannot conduct the attack. This would look something like
CODE :
__________________________________________________________________________
//
A CSRF attack is a form of attack in which commands are transmitted from a victim to another website without the users consent. CSRF attacks are usually invisible and rely on browser functionality (such as automatically loading images).
How is a CSRF Attack Carried Out?
CSRF attacks are embedded in an element browsers automatically react to (such as an image tag).
Lets assume that Joe has just registered with a brand new Electronic Money transfer site. When Joe wants to transfer money, he heads to www.example.com/transfer.php to send some money to his wife, Mary.
He fills out the forms for the amount of money he wants to transfer and who he wants to send the money to, and then clicks submit. The URL now looks like this:
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Joe&to=Mary&amount=2
__________________________________________________________________________
The next day, Janice, Joes angry ex-wife, also registers with the site. She decides to send $5 to her boyfriend, named Sam. She heads to www.example.com/transfer.php, fills out the forms (quite angrily), and hits submit.
She notices that the URL,
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Janice&to=Sam&amount=5
__________________________________________________________________________
does not require any authorization besides her Session cookie (which is automatically send to the web server).
Still bitter over what she thinks was an unfair settlement to her divorce with Joe, she slips on her black hat and decides to cheat Joe out of his money.
She sends a message to Joe which looks like this:
CODE :
__________________________________________________________________________
//Title: I Hate You!!!!
You are the most rotten, vile, PIG ever!!!!!
[img]www.example.com/transfer.php?from=Joe&to=Janice&amount=5000[/img]
__________________________________________________________________________
(Note that Janice used BBCode for her image tag, which example.com automatically translates into HTML.)
Later that day, Joe logs on and views the message. His browser sees the image tag and automatically follows it to
CODE :
__________________________________________________________________________
//www.example.com/transfer.php?from=Joe&to=Janice&amount=5000
__________________________________________________________________________
His browser then attempts to download the page and display it as an image. Because the link provided is not a valid image, the browser displays it as a broken image.
However, the server at example.com sees that Joe has visited the link, and transfers $5000 dollars to Janice.
All this happens invisibly and within seconds.
Dangers of CSRF
We now understand how a CSRF attack is performed. But, what can this attack do?
It can:
*Transfer Funds
*Log a user in/out
*Register a user
*Log data of a user
*Send a message from the victim to someone else
*Etc
The only requirement is that the server must not have a means of detecting if the user has authorized the action that a CSRF attack performs.
Prevention of CSRF Attacks
CSRF attacks can be prevented in a number of ways, but the best way to prevent them is a combination of many different methods.
CSRF attacks are much easier if an action can be performed with an HTTP GET request, but simply having only POST requests is not sufficient to prevent CSRF attacks.
One common method of preventing CSRF attacks is to have a hidden value randomly generated upon the users visit of the webpage. The advantage of this strategy is that the attacker can not predict what the token will be, and thus cannot conduct the attack. This would look something like
CODE :
__________________________________________________________________________
//
Label:
cracker,
cracking,
Deface Website,
hacker,
Hacking,
Internet,
Vulnerability,
website
Assembly Language for Z80 processor on TI83+ Calculator
This article is about assembly langauge for the z80 processor, and running the code on the TI83+ calculator system. The z80 processor is a robust, 16bit processor produced by Zilog. This processor is used in your TI83+ calculator, GameBoy Color, Sega Game Gear, and a fair list of electronics. I'm writing this article for both experienced assembly langauge guru's interested in z80 processor and n00bs who want to get their hands in on the action.
WHY LEARN ASSEMBLY LANGUAGE AT ALL?
I can tell you personally that it is a rewarding langauge to understand because you will have that much more understanding of computers and gives you much more control over memory. This is also the mnemonic code for for a byte instruction set. The byte instruction set is what is used for shellcode!! Shellcoding is part of remote buffer overflows part of leet still legit hacking methods. Another reason is because this is FUN STUFF! come on! get your hands dirty and do some z80. Once you know one assembly language, you can teach yourself any assembly language for any processor.
This article is from information, research and hacking around a couple years ago over a christmas break.
WHAT IS GOIN DOWN IN THIS ARTICLE?
In this article I will explain what you need to set up your coding environment, Learn instructions of z80 processor along with nifty Interrupt Service Routines provided by TI83+ System, write a HelloWorld application and do some simple math instructions, along with tangents I find relevant from personal experience. I hope this is one of 2 or 3 articles, where the second article should cover arrays, conditional statements, and write a Game. The 3rd will cover the stack and monochramatic graphics.
YOU NEED!
-Windows XP (Linux is available, but I couldn't find a decent assembler/linker)
-Silver USB cable available at (http://education.ti.com/educationportal/sites/US/productDetail/us_connectivitycable_silverusb.html)
this is used for transfering files to and from the calc and PC (note: if you're cheap you could make one yourself if you have the skillz :X, if so hats off to you)
-TASM.exe (Table assembler NOT Turbo assembler) This is the assembler
-devpac8x.com This is the linker it generates the executable code that will be the file to upload to calculator
SETTING UP THE ENVIRONMENT?
I'm assuming you have the silver link cable now and the software that came along with it installed on your PC. Now...
1) Now make a folder called z80 and put both the TASM.exe and devpac8x files in same directory.
2) Make a makez80.bat batch File with following code...
CODE :
__________________________________________________________________________
::@Author - xfelix
::@File - makez80.bat
::Description - assemble and link z80 programs
tasm -80 -i -b %1.z80 %1.bin
devpac8x %1
__________________________________________________________________________
3) Open up a DOS shell and move to TASM root directory
Environment is set now let's diggin.
Before you Begin
----------------
Writing instructions and registers are not case sensitive although useing labels are, but as one is learning assembly language they should develop their own style of writing, this can be thought of as your trade mark as a programmer. You can tell alot about a programmer just by the way they write code, and once one has been programming for a while they can tell the difference between a true poet and a script kiddie. So when doing this tutorial take your time, and make sure you are taking in many of the juicy details because this is a jam packed tutorial. Even though this tutorial is broken up in to two parts, any one is welcome to break it up into their own parts, and follow it at their own pace, this is a good strategy to approach this article.
Part 1
-------
Instructions
There are many instructions provided with a processor, which can be thought of as commands to peform some action. An action could be to move data from a register to memory, to add the data of one register to another register, compare two registers, jump to a location in memory, etc. If one has ever done assembly language for the Intel-IA32 processor there are many instructions that you will probably take for granted when working with Z80 processor. The z80
processor does not contain a multiply instruction MUL or a divide instruction DIV like the intel IA-32. One must develop their own clever ways to do this.
Registers
Registers are used for quick access of memory and is what also performs all computations. You can move data from memory to a register in the processor, move data froma a register to memory, and move data from a register to another register, but one may never move memory directly to memory. The Instuction to peform these actions is LD, which is short for load. The format of this instruction is
LD DESTINATION, SOURCE
where DESTINATION can be any register or memory address, and SOURCE can be any register or memory location. What ever the type of data storage it is (memory or register) it will move the data in the SOURCE storage to the DESTINATION storage. One can also use constant number values as the source seen in the sample code below...
First a table of the z80 register names for 8 bit and 16 bit, then some sample code.
8 bit registers
---------------
A - 8 bit accumulator register
B - general purpose / b is high byte of BC register
C - general purpose / C is low byte of BC register
D - general purpose / D is high byte of DE register
E - general purpose / E is low byte of DE register
H - H is high byte of HL register
L - L is low byte of HL register
16 bit registers
-----------------
BC - general purpose/base pointer register
DE - general purpose register
HL - 16 bit accumulator register
SP - stack pointer
IX - Index register
IY - Index register
I don't use the last two register IX and IY very often since they both contain (I) register, which can make life hell, so I avoid them at all costs, but there are times when they are necesarry.
SAMPLE
------
CODE :
__________________________________________________________________________
LD a, b ;moves the contents of register b to register a
__________________________________________________________________________
CODE :
__________________________________________________________________________
LD a, $10 ;moves the constant hexadecimal number 10
LD b, a ;now we move the contents of a to b
LD HL, memoryData ;moves the memoryData memory address into HL,
LD (HL), b ;moves the contents of b into the memory address storage
memoryData: .db 0 ;memoryData variable initialized to zero
__________________________________________________________________________
*****CAUTION****
I do not recommend moving data into memory similar to the following example
CODE :
__________________________________________________________________________
LD ($FFFF), a
__________________________________________________________________________
...although this is valid and will execute your calculator will most likely crash and your RAM will erase itself and you will have a freshly wiped RAM on your hands. While programming on your TI83+ it will most likely crash often, even if you only have logic errors. This is due to the fact that programming on your calcuator is in REAL mode, unlike when you program on your computer which is in PROTECTED mode.
HelloWorld
If you have not figured out by now a semi-colon ; is a comment in TASM and most other assembly languages. The white spaces used before and after the instruction is a TAB space, TASM will not like your code if you don't use a TAB space inbetween your instruction and storage placers.
CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 12/05/09
;@file - hello.z80
;@description - This is a HelloWorld application for learning how to
; develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b hello.z80 hello.bin (For linking)
; devpac8x hello (For byte code)
;***************************************************************************
#include "ti83plus.inc"
.list
.org $9d93
.db $bb,$6d
code: xor a ;zero a by exlusive or-ing it by itself
ld h, a ;load a into h
ld l, a ;load a into l
ld (PenCol), hl ;put hl in PenCol memory
ld hl, str1
bcall(_PutS) ;_PutS takes HL register as parameter
bcall(_NewLine)
ret
data:
str1: .db "Hello World!! w00t, calc codez (^_^!)", 0
.end
.end
__________________________________________________________________________
Explanation
Line 1 #include "ti83plus.inc"
The #include directive is similar to the one in C only instead of including .h (header files) you can include .inc (include files). The ti83plus.inc file contains names of kernel functions and important memory locations used by the mirageOS.
Line 2 .list
Line 3 .org $9d93
Line 4 .db $bb,$6d
make sure these lines are always in any program you ever run. Line 3 contains the .org directive, which specifies where in memory the application will run, which is always $9d93. Make sure this number does not change because your program will not run correctly and crash your calculator, I was writing a program before and accidently typed $9593 instead, but it took me a long time to figure out why my application wasn't working. It is suddle details like this that can hold you back. Line 4 .db (define byte) will define two bytes at the very beginning of the program $bb,$6d. These two bytes are magic numbers that the mirageOS will like to see to make sure it's executing a valid TI83+ progam.
Line 5 xor a
The only instruction in this program that you have not seen before is xor, which will perform an exlusive or operation on the register given with the a register. Since I have given the (a) register, the operation will be a XOR a, which zero out the a register. If I had the following sample code
xor b ;Then the operation will become a XOR b
You should know what Line 6-10 does by reading the comments, but I would like to explain more Line 11
Line 11 bcall(_PutS)
bcall instruction is defined in the include file as well as the (_PutS) function name. The kernel function (_PutS) takes the hl register as a parameter, which should be the memory address of the string you would like to be displayed. The (_NewLine) kernel function will go to the next line for printing data or recieving input.
Line 14 ret
The ret instuction returns to the memory location that called the executuable. This memory location is stored in the stack, but I will talk more about the stack and procedures in the 3rd article.
Labels
---------------
There are three labels in this program and two of them are optional that I put in for clarity, so I know where my code section and data section are located. The code section is where your code should be, and the data section is where you should declare all of your variables. Here is how you declare a string variable
Line 16 str1: .db "Hello World!! w00t, calc codez (^_^!)", 0
Notice the name of the variable is just a label followed by a .db (define byte). Inorder to declare a 16 bit variable you would use the following sample code
CODE :
__________________________________________________________________________
myNum: .dw $1337
__________________________________________________________________________
... which is a .dw (define word) a 16 bit variable myNum, set to a value of $1337 in hexadecimal. Typically the data section is before the code section, but people who write viruses and shellcode will put the code section first followed by data section ^.^ Try to rewrite the hello application so that the data section comes before the code section.
Make sure there are two .ends at the end of the file since who ever wrote TASM screwed up and expected two .ends as if it's already not hard enough to make a typo mistake.
Compiling
----------

Make sure you save the file as a .z80 file, I called mine hello.z80. Then type the following in command prompt makez80 hello and should then assemble and link the file like in this image.

Now once this is accomplised this makez80 has assembled and linked your application, which has generated a TI83+ executable file hello.8XP. Asssuming you have installed the software that came with your TI83+ silver link cable, right click the file and hit send to TI device, and you will get a menu like this
It will automatically start the transfer after a short time has passed.
Now pick up your TI83+ calculator and hit the PRGM button and you should see your application sitting in RAM Hello. To Run this program you must hit
-2nd Catalog
-Choice Asm(
-Now hit the PRGM button
-Choose the Hello application
-Now hit ENTER
Your application should have run and exited very quickly ^^ congradulations!! you've run your first application on the z80 processor. Now take a break or play around with the output text or what not, but wait to continue to Part 2 of this paper, you have taken in alot of information. But before I begin part 2 here is another useful kernel function bcall(_DispHL) (display HL register), this function will dump what ever data is stored in the HL registers, so feel free to play around with loading data from memory to registers during this grace period :D
Part 2
------------------
Math instructions
I will discuss the following math instructions ADD, INC, DEC, SUB, and SRL, but there are many more. Check the references for an entire list of the Z80 processor instructions set and more. The format of these instructions is similar to the LD instruction only when adding the 8 bit registers make sure that the (A) register is always getting added to, and for 16 bit registers either the HL,IX, or IY registers. This is because A and HL registers are considered the accumulator registers for their respective size, it's just how it is. All assembly languages have their accumulator registers, only Z80 takes advantage and is more strict then any 32 bit processor. Say we have to following sample code
CODE :
__________________________________________________________________________
LD HL, $10
LD DE, $5
ADD HL, DE ;Add the contents of DE register to the HL register
bcall(_DispHL) ;dump the HL register in decimal notation
__________________________________________________________________________
This will add the contents of the DE register to the contents of the HL register. After the ADD instruction is executed the HL register will equal $15 and the DE register will equal $5. When executed the following output of this sample code will be 21. Caution the z80 processor does not support the following instruction
CODE :
__________________________________________________________________________
ADD BC, DE
__________________________________________________________________________
it's simply not supported by the Z80 processor to peform this operation, which can cause headaches ontop of headaches at times. One may also add to a register directly from memory, but never to memory from a register. Check out the next example
CODE :
__________________________________________________________________________
remainingHealth: .db $35
LD A, $65 ;damage after getting knifed in counter strike sorce into B register
LD HL, remainingHealth ;HL register points to remainingHealth memory address
ADD A, (HL) ;adds the contents from the memory to the B register
;There is a suddle problem in the above code can you think what it is?? Hint what is the maximum number that can fit into an 8 bit register?
;Can you fix it??
__________________________________________________________________________
When you load the memory address of the variable into the HL register, it is essentially pointing to that place in memory, which is similar to how pointers in C and C++ work. When you put parantesis around the HL register you are accessing the byte data at the location in memory. To give you an idea of how working with arrays would work to get the next item in the array you would use (HL+1), then (HL+2), etc. How would you display the register in A?? here is the following code
CODE :
__________________________________________________________________________
LD HL, 0 ;zero/clean out the HL register
LD L, A ;Load A register into lower register of HL register
bcall(_DispHL) ;Display HL register contents
__________________________________________________________________________
The subtract instruction will substract the contents of the specified register from the A register. Here is a following sample code
CODE :
__________________________________________________________________________
LD A, $FF ;Load the hex value $FF into the A register
LD B, $FE ;Load the hex value $FE into the B register
SUB B ;Subtract the contents of B register from A register, aka A=A-B
__________________________________________________________________________
After the following sample code is executed the A register will be equal to 1. The next two instructions are insanely easy to follow INC and DEC. The INC instruction will increment a register by 1, and the DEC instruction will decrement a register by 1.
CODE :
__________________________________________________________________________
DEC HL ;decrement HL by 1
INC HL ;increment HL by 1
__________________________________________________________________________
HL register will not be changed after the execution of the previous sample code. Now the next instruction that will be discussed is the srl instruction, which stands for (Shift Right Logical). This performs a bitwise operation of shifting the bits to the right by 1 on the specified register. Shifting bits to the right on a register is like dividing the contents of the register by 2^n where n is the number of shifts to the right. If we had the following value in the A register $FF then A will look like this in binary:
A: 11111111 //Also equal to 256 in decimal notation
Now if we call the SRL instruction like this
CODE :
__________________________________________________________________________
SRL A
__________________________________________________________________________
All the bits in the A register will be shifted to the right and drop off the right most bit to the carry flag. I will discuss more on flags and their purpose in the 2nd article when I talk about conditional statements, loops, etc. Now the A register looks like this
A: 01111111 //Also equal to 128 in decimal notation or 256/2 which is what happen after the SRL instruction executed
Now let's right a useful application with the knowledge you've accumulated. The application that We will write is one that will determine the first five numbers of the fibonacci sequence. It's important to note that this code would be alot shorter if we had learned loops, which we haven't yet and/or the use of macros and procedures which are also in later articles. Anyway here is the code that will display the first 5 numbers of the fibonaccie squeunce. It is also important to note that (_NewLine) will destroy all registers:(
CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 01/06/10
;@file - fib.z80
;@description - This is a Fibonacci sequence application that will determine the first
; 5 numbers of the Fibonacci sequence. This application is for learning
; how to develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b fib.z80 fib.bin (For linking)
; devpac8x fib (For byte code)
;***************************************************************************
#include "ti83plus.inc"
.list
.org $9d93
.db $bb, $6d
code:
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
LD L, A
bcall(_DispHL)
bcall(_NewLine) ;Destroy Registers in process of going to new line
LD HL, $0000
LD L, B
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A, B
LD (firstNum), A ;save the third number to first number
LD L, A
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A, B
LD (secondNum), A ;save the fourth number to second number
LD L, A
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A,B
LD L, A
bcall(_DispHL)
bcall(_NewLine)
ret
Data:
firstNum: .db $1
secondNum: .db $1
.end
.end
__________________________________________________________________________
Final Notes
--------------------
This ends the first article of programming in assembly language for the z80 processor on your TI83+ calculator. I hope it was useful and you picked up a thing or two about assembly language. I have listed references below for instruction set and tutorial/ code examples, which should be useful, you don't have to wait for the second article inorder to continue your quest of learning z80 assembler. Once you have been working with assembly language you have my permission to walk proudly amoung your programmer/hacker peers, and can look down on those who don't know assembly language. You are now apart of the z80 scene.
References
-------------------
z80 Heaven tutorials http://z80-heaven.wikidot.com/system:tutorials
z80 instruction set http://nemesis.lonestar.org/computers/tandy/software/apps/m4/qd/opcodes.html
official Zilog manual http://www.zilog.com/docs/z80/um0080.pdf
WHY LEARN ASSEMBLY LANGUAGE AT ALL?
I can tell you personally that it is a rewarding langauge to understand because you will have that much more understanding of computers and gives you much more control over memory. This is also the mnemonic code for for a byte instruction set. The byte instruction set is what is used for shellcode!! Shellcoding is part of remote buffer overflows part of leet still legit hacking methods. Another reason is because this is FUN STUFF! come on! get your hands dirty and do some z80. Once you know one assembly language, you can teach yourself any assembly language for any processor.
This article is from information, research and hacking around a couple years ago over a christmas break.
WHAT IS GOIN DOWN IN THIS ARTICLE?
In this article I will explain what you need to set up your coding environment, Learn instructions of z80 processor along with nifty Interrupt Service Routines provided by TI83+ System, write a HelloWorld application and do some simple math instructions, along with tangents I find relevant from personal experience. I hope this is one of 2 or 3 articles, where the second article should cover arrays, conditional statements, and write a Game. The 3rd will cover the stack and monochramatic graphics.
YOU NEED!
-Windows XP (Linux is available, but I couldn't find a decent assembler/linker)
-Silver USB cable available at (http://education.ti.com/educationportal/sites/US/productDetail/us_connectivitycable_silverusb.html)
this is used for transfering files to and from the calc and PC (note: if you're cheap you could make one yourself if you have the skillz :X, if so hats off to you)
-TASM.exe (Table assembler NOT Turbo assembler) This is the assembler
-devpac8x.com This is the linker it generates the executable code that will be the file to upload to calculator
SETTING UP THE ENVIRONMENT?
I'm assuming you have the silver link cable now and the software that came along with it installed on your PC. Now...
1) Now make a folder called z80 and put both the TASM.exe and devpac8x files in same directory.
2) Make a makez80.bat batch File with following code...
CODE :
__________________________________________________________________________
::@Author - xfelix
::@File - makez80.bat
::Description - assemble and link z80 programs
tasm -80 -i -b %1.z80 %1.bin
devpac8x %1
__________________________________________________________________________
3) Open up a DOS shell and move to TASM root directory
Environment is set now let's diggin.
Before you Begin
----------------
Writing instructions and registers are not case sensitive although useing labels are, but as one is learning assembly language they should develop their own style of writing, this can be thought of as your trade mark as a programmer. You can tell alot about a programmer just by the way they write code, and once one has been programming for a while they can tell the difference between a true poet and a script kiddie. So when doing this tutorial take your time, and make sure you are taking in many of the juicy details because this is a jam packed tutorial. Even though this tutorial is broken up in to two parts, any one is welcome to break it up into their own parts, and follow it at their own pace, this is a good strategy to approach this article.
Part 1
-------
Instructions
There are many instructions provided with a processor, which can be thought of as commands to peform some action. An action could be to move data from a register to memory, to add the data of one register to another register, compare two registers, jump to a location in memory, etc. If one has ever done assembly language for the Intel-IA32 processor there are many instructions that you will probably take for granted when working with Z80 processor. The z80
processor does not contain a multiply instruction MUL or a divide instruction DIV like the intel IA-32. One must develop their own clever ways to do this.
Registers
Registers are used for quick access of memory and is what also performs all computations. You can move data from memory to a register in the processor, move data froma a register to memory, and move data from a register to another register, but one may never move memory directly to memory. The Instuction to peform these actions is LD, which is short for load. The format of this instruction is
LD DESTINATION, SOURCE
where DESTINATION can be any register or memory address, and SOURCE can be any register or memory location. What ever the type of data storage it is (memory or register) it will move the data in the SOURCE storage to the DESTINATION storage. One can also use constant number values as the source seen in the sample code below...
First a table of the z80 register names for 8 bit and 16 bit, then some sample code.
8 bit registers
---------------
A - 8 bit accumulator register
B - general purpose / b is high byte of BC register
C - general purpose / C is low byte of BC register
D - general purpose / D is high byte of DE register
E - general purpose / E is low byte of DE register
H - H is high byte of HL register
L - L is low byte of HL register
16 bit registers
-----------------
BC - general purpose/base pointer register
DE - general purpose register
HL - 16 bit accumulator register
SP - stack pointer
IX - Index register
IY - Index register
I don't use the last two register IX and IY very often since they both contain (I) register, which can make life hell, so I avoid them at all costs, but there are times when they are necesarry.
SAMPLE
------
CODE :
__________________________________________________________________________
LD a, b ;moves the contents of register b to register a
__________________________________________________________________________
CODE :
__________________________________________________________________________
LD a, $10 ;moves the constant hexadecimal number 10
LD b, a ;now we move the contents of a to b
LD HL, memoryData ;moves the memoryData memory address into HL,
LD (HL), b ;moves the contents of b into the memory address storage
memoryData: .db 0 ;memoryData variable initialized to zero
__________________________________________________________________________
*****CAUTION****
I do not recommend moving data into memory similar to the following example
CODE :
__________________________________________________________________________
LD ($FFFF), a
__________________________________________________________________________
...although this is valid and will execute your calculator will most likely crash and your RAM will erase itself and you will have a freshly wiped RAM on your hands. While programming on your TI83+ it will most likely crash often, even if you only have logic errors. This is due to the fact that programming on your calcuator is in REAL mode, unlike when you program on your computer which is in PROTECTED mode.
HelloWorld
If you have not figured out by now a semi-colon ; is a comment in TASM and most other assembly languages. The white spaces used before and after the instruction is a TAB space, TASM will not like your code if you don't use a TAB space inbetween your instruction and storage placers.
CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 12/05/09
;@file - hello.z80
;@description - This is a HelloWorld application for learning how to
; develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b hello.z80 hello.bin (For linking)
; devpac8x hello (For byte code)
;***************************************************************************
#include "ti83plus.inc"
.list
.org $9d93
.db $bb,$6d
code: xor a ;zero a by exlusive or-ing it by itself
ld h, a ;load a into h
ld l, a ;load a into l
ld (PenCol), hl ;put hl in PenCol memory
ld hl, str1
bcall(_PutS) ;_PutS takes HL register as parameter
bcall(_NewLine)
ret
data:
str1: .db "Hello World!! w00t, calc codez (^_^!)", 0
.end
.end
__________________________________________________________________________
Explanation
Line 1 #include "ti83plus.inc"
The #include directive is similar to the one in C only instead of including .h (header files) you can include .inc (include files). The ti83plus.inc file contains names of kernel functions and important memory locations used by the mirageOS.
Line 2 .list
Line 3 .org $9d93
Line 4 .db $bb,$6d
make sure these lines are always in any program you ever run. Line 3 contains the .org directive, which specifies where in memory the application will run, which is always $9d93. Make sure this number does not change because your program will not run correctly and crash your calculator, I was writing a program before and accidently typed $9593 instead, but it took me a long time to figure out why my application wasn't working. It is suddle details like this that can hold you back. Line 4 .db (define byte) will define two bytes at the very beginning of the program $bb,$6d. These two bytes are magic numbers that the mirageOS will like to see to make sure it's executing a valid TI83+ progam.
Line 5 xor a
The only instruction in this program that you have not seen before is xor, which will perform an exlusive or operation on the register given with the a register. Since I have given the (a) register, the operation will be a XOR a, which zero out the a register. If I had the following sample code
xor b ;Then the operation will become a XOR b
You should know what Line 6-10 does by reading the comments, but I would like to explain more Line 11
Line 11 bcall(_PutS)
bcall instruction is defined in the include file as well as the (_PutS) function name. The kernel function (_PutS) takes the hl register as a parameter, which should be the memory address of the string you would like to be displayed. The (_NewLine) kernel function will go to the next line for printing data or recieving input.
Line 14 ret
The ret instuction returns to the memory location that called the executuable. This memory location is stored in the stack, but I will talk more about the stack and procedures in the 3rd article.
Labels
---------------
There are three labels in this program and two of them are optional that I put in for clarity, so I know where my code section and data section are located. The code section is where your code should be, and the data section is where you should declare all of your variables. Here is how you declare a string variable
Line 16 str1: .db "Hello World!! w00t, calc codez (^_^!)", 0
Notice the name of the variable is just a label followed by a .db (define byte). Inorder to declare a 16 bit variable you would use the following sample code
CODE :
__________________________________________________________________________
myNum: .dw $1337
__________________________________________________________________________
... which is a .dw (define word) a 16 bit variable myNum, set to a value of $1337 in hexadecimal. Typically the data section is before the code section, but people who write viruses and shellcode will put the code section first followed by data section ^.^ Try to rewrite the hello application so that the data section comes before the code section.
Make sure there are two .ends at the end of the file since who ever wrote TASM screwed up and expected two .ends as if it's already not hard enough to make a typo mistake.
Compiling
----------

Make sure you save the file as a .z80 file, I called mine hello.z80. Then type the following in command prompt makez80 hello and should then assemble and link the file like in this image.

Now once this is accomplised this makez80 has assembled and linked your application, which has generated a TI83+ executable file hello.8XP. Asssuming you have installed the software that came with your TI83+ silver link cable, right click the file and hit send to TI device, and you will get a menu like this
It will automatically start the transfer after a short time has passed.
Now pick up your TI83+ calculator and hit the PRGM button and you should see your application sitting in RAM Hello. To Run this program you must hit
-2nd Catalog
-Choice Asm(
-Now hit the PRGM button
-Choose the Hello application
-Now hit ENTER
Your application should have run and exited very quickly ^^ congradulations!! you've run your first application on the z80 processor. Now take a break or play around with the output text or what not, but wait to continue to Part 2 of this paper, you have taken in alot of information. But before I begin part 2 here is another useful kernel function bcall(_DispHL) (display HL register), this function will dump what ever data is stored in the HL registers, so feel free to play around with loading data from memory to registers during this grace period :D
Part 2
------------------
Math instructions
I will discuss the following math instructions ADD, INC, DEC, SUB, and SRL, but there are many more. Check the references for an entire list of the Z80 processor instructions set and more. The format of these instructions is similar to the LD instruction only when adding the 8 bit registers make sure that the (A) register is always getting added to, and for 16 bit registers either the HL,IX, or IY registers. This is because A and HL registers are considered the accumulator registers for their respective size, it's just how it is. All assembly languages have their accumulator registers, only Z80 takes advantage and is more strict then any 32 bit processor. Say we have to following sample code
CODE :
__________________________________________________________________________
LD HL, $10
LD DE, $5
ADD HL, DE ;Add the contents of DE register to the HL register
bcall(_DispHL) ;dump the HL register in decimal notation
__________________________________________________________________________
This will add the contents of the DE register to the contents of the HL register. After the ADD instruction is executed the HL register will equal $15 and the DE register will equal $5. When executed the following output of this sample code will be 21. Caution the z80 processor does not support the following instruction
CODE :
__________________________________________________________________________
ADD BC, DE
__________________________________________________________________________
it's simply not supported by the Z80 processor to peform this operation, which can cause headaches ontop of headaches at times. One may also add to a register directly from memory, but never to memory from a register. Check out the next example
CODE :
__________________________________________________________________________
remainingHealth: .db $35
LD A, $65 ;damage after getting knifed in counter strike sorce into B register
LD HL, remainingHealth ;HL register points to remainingHealth memory address
ADD A, (HL) ;adds the contents from the memory to the B register
;There is a suddle problem in the above code can you think what it is?? Hint what is the maximum number that can fit into an 8 bit register?
;Can you fix it??
__________________________________________________________________________
When you load the memory address of the variable into the HL register, it is essentially pointing to that place in memory, which is similar to how pointers in C and C++ work. When you put parantesis around the HL register you are accessing the byte data at the location in memory. To give you an idea of how working with arrays would work to get the next item in the array you would use (HL+1), then (HL+2), etc. How would you display the register in A?? here is the following code
CODE :
__________________________________________________________________________
LD HL, 0 ;zero/clean out the HL register
LD L, A ;Load A register into lower register of HL register
bcall(_DispHL) ;Display HL register contents
__________________________________________________________________________
The subtract instruction will substract the contents of the specified register from the A register. Here is a following sample code
CODE :
__________________________________________________________________________
LD A, $FF ;Load the hex value $FF into the A register
LD B, $FE ;Load the hex value $FE into the B register
SUB B ;Subtract the contents of B register from A register, aka A=A-B
__________________________________________________________________________
After the following sample code is executed the A register will be equal to 1. The next two instructions are insanely easy to follow INC and DEC. The INC instruction will increment a register by 1, and the DEC instruction will decrement a register by 1.
CODE :
__________________________________________________________________________
DEC HL ;decrement HL by 1
INC HL ;increment HL by 1
__________________________________________________________________________
HL register will not be changed after the execution of the previous sample code. Now the next instruction that will be discussed is the srl instruction, which stands for (Shift Right Logical). This performs a bitwise operation of shifting the bits to the right by 1 on the specified register. Shifting bits to the right on a register is like dividing the contents of the register by 2^n where n is the number of shifts to the right. If we had the following value in the A register $FF then A will look like this in binary:
A: 11111111 //Also equal to 256 in decimal notation
Now if we call the SRL instruction like this
CODE :
__________________________________________________________________________
SRL A
__________________________________________________________________________
All the bits in the A register will be shifted to the right and drop off the right most bit to the carry flag. I will discuss more on flags and their purpose in the 2nd article when I talk about conditional statements, loops, etc. Now the A register looks like this
A: 01111111 //Also equal to 128 in decimal notation or 256/2 which is what happen after the SRL instruction executed
Now let's right a useful application with the knowledge you've accumulated. The application that We will write is one that will determine the first five numbers of the fibonacci sequence. It's important to note that this code would be alot shorter if we had learned loops, which we haven't yet and/or the use of macros and procedures which are also in later articles. Anyway here is the code that will display the first 5 numbers of the fibonaccie squeunce. It is also important to note that (_NewLine) will destroy all registers:(
CODE :
__________________________________________________________________________
;***************************************************************************
;@author - xfelix
;@date - 01/06/10
;@file - fib.z80
;@description - This is a Fibonacci sequence application that will determine the first
; 5 numbers of the Fibonacci sequence. This application is for learning
; how to develop z80 applications for TI83+ Calculator :D
;Compile Instructions: tasm -80 -i -b fib.z80 fib.bin (For linking)
; devpac8x fib (For byte code)
;***************************************************************************
#include "ti83plus.inc"
.list
.org $9d93
.db $bb, $6d
code:
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
LD L, A
bcall(_DispHL)
bcall(_NewLine) ;Destroy Registers in process of going to new line
LD HL, $0000
LD L, B
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A, B
LD (firstNum), A ;save the third number to first number
LD L, A
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A, B
LD (secondNum), A ;save the fourth number to second number
LD L, A
bcall(_DispHL)
bcall(_NewLine)
LD A, (firstNum)
LD HL, secondNum
LD B, (HL)
LD HL, $0000
ADD A,B
LD L, A
bcall(_DispHL)
bcall(_NewLine)
ret
Data:
firstNum: .db $1
secondNum: .db $1
.end
.end
__________________________________________________________________________
Final Notes
--------------------
This ends the first article of programming in assembly language for the z80 processor on your TI83+ calculator. I hope it was useful and you picked up a thing or two about assembly language. I have listed references below for instruction set and tutorial/ code examples, which should be useful, you don't have to wait for the second article inorder to continue your quest of learning z80 assembler. Once you have been working with assembly language you have my permission to walk proudly amoung your programmer/hacker peers, and can look down on those who don't know assembly language. You are now apart of the z80 scene.
References
-------------------
z80 Heaven tutorials http://z80-heaven.wikidot.com/system:tutorials
z80 instruction set http://nemesis.lonestar.org/computers/tandy/software/apps/m4/qd/opcodes.html
official Zilog manual http://www.zilog.com/docs/z80/um0080.pdf
Label:
assembly,
hacker,
Internet,
programming,
Scripting
Introduction to Modern Steganography
This article introduces steganography and explains some of its techniques and methods supported by examples. My objective was to make this post as short as possible while covering all important information. Your comments are welcome for any possible enhancements or for future articles about steganography by me or other people.
Steganography
Steganography is all the techniques used to exchange secret messages without drawing attention. It is the science of hiding information.
Some of the old school methods to hide information are: invisible ink, null ciphers, microdots or the use of pinpricks, deliberate misspelling or slightly different font to mark certain words in messages and maps.
Null cipher
It’s a normal text written in the clear, but includes a hidden message. For example:
"Fishing freshwater bends and saltwater coasts rewards anyone feeling stressed. Resourceful anglers usually find masterful leapers fun and admit swordfish rank overwhelming anyday." [2]
If we take out the third letter in each word, we get: Send Lawyers, Guns, and Money.
Modern steganography refers to hiding information in digital images, audio files or even video. There are many methods and tools to do that. Nevertheless, and to have double protection, secret messages are first encrypted and then hidden using a steganography tool.
The steganographic process can be described with the following formula:
Cover medium + Data to hide + Stego key* = Stego Medium
* Note that if no encryption is added, there is no need for a Stego key.
Hiding messages in pictures
This is usually done by:
1. LSB (Least Significant Bit insertion).
2. Masking & filtering.
3. Algorithms & transformations.
Using LSB is famous, so I will choose it to explain how data can be hidden in images.
LSB is always the last bit on the right-hand side of any binary number. Changing this bit causes the least possible effect to the original value.
In a 24-bit image, there are 3 bytes of data to represent RGB values for every pixel in that image. This implies that we can store/hide 3 bits in every pixel. For example, if the image
has the following bits:
10010101 00001101 11001001
10010110 00001111 11001010
10011111 00010000 11001011
To store 101101101. we replace with the original LSBs like this:
10010101 00001100 11001001
10010111 00001110 11001011
10011111 00010000 11001011
To reveal the stored message, the LSBs are extracted alone from the Stego Medium and combined together.
Hiding messages in audio files
Two known methods to store message in audio files are: Frequency Domain and Time Domain.
In Frequency Domain, a message can be stored in practically unused frequencies of audio files. For instance, In a CD where the sample rate is 44.1 kHz, the highest frequency without aliasing is 22.05 kHz.
Now, because the average peak frequency that an adult can hear is approximately 18 kHz, this leaves 4 kHz of frequency that is "practically unused". This space can then be used to hide a message (a copyright message for example).
In Time Domain, a message can be stored in the LSBs, something similar to what we saw with images. To maintain CD quality, it is important to encode at 16 bits per sample at a rate of 44.1kHz. However, we can also record at 8 bits per sample using the high significant bits (first bits on your left-hand side) and save the other 4 LSBs to hide our message without making any perceptible change to the audio quality.
In a comparison between the two, detecting messages hidden with time domain is harder because it requires more resources. [4]
Watermarking (digital watermarking)
Whenever there is a topic about steganography now a day, Digital Watermarking is also mentioned. It refers to embedding hidden messages as well, but not for the purpose of sending secret information. Instead, Watermarking is usually used for the following:
1. Copyright protection: include ownership information.
2. Copy protection: include instructions to stop data copying devices from making and distributing copies of the original.
3. Prove data authenticity.
4. Tracking: If copies of a file are distributed illegally, the source can be revealed if the master copies had unique watermarks included.
Stego Tools
The following freeware tools have been tested by me on Windows 7 and they work great:
1. 4t HIT Mail Privacy LITE 1.01
2. S-Tools 4.0
To find more tools (commercials and freeware) make use of the following lists as they are the best I found online or do your own googling:
1.http://home.comcast.net/~ebm.md/stego/software.html
2.http://www.jjtc.com/Security/stegtools.htm
Steganalyses and countermeasures
Steganalyses aim to investigate suspected information to determine whether they include any sealed data and reveal the hidden message if exist.
Any unusual patterns (visual or statistical) are usually analyzed to detect suspected information. Hence, any method can be useful, for instance, image editors and hex editors (e.g. HEX Workshop).
Some methods are designed and developed to detect and reveal information hidden by known steganography tools. There are also enhanced and powerful digital forensic analysis
tools such as StegAlyzerSS (Steganography Analyzer Signature Scanner) developed by the Steganography Analysis and Research Center [5].
Conclusion note
The references at the end of this article are quite informative, have a go on them in your free time if you are looking for more details.
References
[1] Introduction to Steganography. [cited 2010 Jan 08]; Available from: http://www.infosyssec.com/infosyssec/Steganography/menu.htm
[2] Johnson, N. F., Duric, Z., Jajodia, S. Information Hiding: Steganography and Watermarking - Attacks and Countermeasures. Kluwer Academic Press. Norwrll, MA, New York, The
Hague, London, 2000.
[3] Gary C. Kessler. Steganography: Hiding Data Within Data. 2001 [cited 2010 Jan 08]; Available from: http://www.garykessler.net/library/steganography.html
[4] Steganography in Signals. [cited 2010 Jan 09]; Available from: http://www.owlnet.rice.edu/~elec301/Projects01/smokey_steg/steg.html
[5] Steganography Analyzer Signature Scanner. [cited 2010 Jan 09]; Available from: http://www.sarc-wv.com/stegalyzerss.aspx
Steganography
Steganography is all the techniques used to exchange secret messages without drawing attention. It is the science of hiding information.
Some of the old school methods to hide information are: invisible ink, null ciphers, microdots or the use of pinpricks, deliberate misspelling or slightly different font to mark certain words in messages and maps.
Null cipher
It’s a normal text written in the clear, but includes a hidden message. For example:
"Fishing freshwater bends and saltwater coasts rewards anyone feeling stressed. Resourceful anglers usually find masterful leapers fun and admit swordfish rank overwhelming anyday." [2]
If we take out the third letter in each word, we get: Send Lawyers, Guns, and Money.
Modern steganography refers to hiding information in digital images, audio files or even video. There are many methods and tools to do that. Nevertheless, and to have double protection, secret messages are first encrypted and then hidden using a steganography tool.
The steganographic process can be described with the following formula:
Cover medium + Data to hide + Stego key* = Stego Medium
* Note that if no encryption is added, there is no need for a Stego key.
Hiding messages in pictures
This is usually done by:
1. LSB (Least Significant Bit insertion).
2. Masking & filtering.
3. Algorithms & transformations.
Using LSB is famous, so I will choose it to explain how data can be hidden in images.
LSB is always the last bit on the right-hand side of any binary number. Changing this bit causes the least possible effect to the original value.
In a 24-bit image, there are 3 bytes of data to represent RGB values for every pixel in that image. This implies that we can store/hide 3 bits in every pixel. For example, if the image
has the following bits:
10010101 00001101 11001001
10010110 00001111 11001010
10011111 00010000 11001011
To store 101101101. we replace with the original LSBs like this:
10010101 00001100 11001001
10010111 00001110 11001011
10011111 00010000 11001011
To reveal the stored message, the LSBs are extracted alone from the Stego Medium and combined together.
Hiding messages in audio files
Two known methods to store message in audio files are: Frequency Domain and Time Domain.
In Frequency Domain, a message can be stored in practically unused frequencies of audio files. For instance, In a CD where the sample rate is 44.1 kHz, the highest frequency without aliasing is 22.05 kHz.
Now, because the average peak frequency that an adult can hear is approximately 18 kHz, this leaves 4 kHz of frequency that is "practically unused". This space can then be used to hide a message (a copyright message for example).
In Time Domain, a message can be stored in the LSBs, something similar to what we saw with images. To maintain CD quality, it is important to encode at 16 bits per sample at a rate of 44.1kHz. However, we can also record at 8 bits per sample using the high significant bits (first bits on your left-hand side) and save the other 4 LSBs to hide our message without making any perceptible change to the audio quality.
In a comparison between the two, detecting messages hidden with time domain is harder because it requires more resources. [4]
Watermarking (digital watermarking)
Whenever there is a topic about steganography now a day, Digital Watermarking is also mentioned. It refers to embedding hidden messages as well, but not for the purpose of sending secret information. Instead, Watermarking is usually used for the following:
1. Copyright protection: include ownership information.
2. Copy protection: include instructions to stop data copying devices from making and distributing copies of the original.
3. Prove data authenticity.
4. Tracking: If copies of a file are distributed illegally, the source can be revealed if the master copies had unique watermarks included.
Stego Tools
The following freeware tools have been tested by me on Windows 7 and they work great:
1. 4t HIT Mail Privacy LITE 1.01
2. S-Tools 4.0
To find more tools (commercials and freeware) make use of the following lists as they are the best I found online or do your own googling:
1.http://home.comcast.net/~ebm.md/stego/software.html
2.http://www.jjtc.com/Security/stegtools.htm
Steganalyses and countermeasures
Steganalyses aim to investigate suspected information to determine whether they include any sealed data and reveal the hidden message if exist.
Any unusual patterns (visual or statistical) are usually analyzed to detect suspected information. Hence, any method can be useful, for instance, image editors and hex editors (e.g. HEX Workshop).
Some methods are designed and developed to detect and reveal information hidden by known steganography tools. There are also enhanced and powerful digital forensic analysis
tools such as StegAlyzerSS (Steganography Analyzer Signature Scanner) developed by the Steganography Analysis and Research Center [5].
Conclusion note
The references at the end of this article are quite informative, have a go on them in your free time if you are looking for more details.
References
[1] Introduction to Steganography. [cited 2010 Jan 08]; Available from: http://www.infosyssec.com/infosyssec/Steganography/menu.htm
[2] Johnson, N. F., Duric, Z., Jajodia, S. Information Hiding: Steganography and Watermarking - Attacks and Countermeasures. Kluwer Academic Press. Norwrll, MA, New York, The
Hague, London, 2000.
[3] Gary C. Kessler. Steganography: Hiding Data Within Data. 2001 [cited 2010 Jan 08]; Available from: http://www.garykessler.net/library/steganography.html
[4] Steganography in Signals. [cited 2010 Jan 09]; Available from: http://www.owlnet.rice.edu/~elec301/Projects01/smokey_steg/steg.html
[5] Steganography Analyzer Signature Scanner. [cited 2010 Jan 09]; Available from: http://www.sarc-wv.com/stegalyzerss.aspx
Label:
cracker,
cracking,
dencryption,
Encryption,
hacker,
Internet,
Steganography
Programming Mobile Phone Applications in Java
._______________________________________________.
| Programming Mobile Phone Applications in Java |
| OVERVIEW |
| |
| Author: ELJONTO (eljonto@live.com) |
|_______________________________________________|
*NOTE: The original content / code IS nicely indented…
CONTENTS:
-Introduction
-User Requirements
-Configurations, Profiles and Optional Packages
-How to start
-Portability
-Parts of a J2ME program
-Drawing and Graphics
-File Handling
-Program Action and Interaction
*Catching keys
*Using CommandListener & softkeys
*Predefined controls and High Level UI elements
-Alert
-List
-TextBox
-Ticker
-Form
-ChoiceGroup
-CustomItem
-DateField
-Gauge
-ImageItem
-Spacer
-StringItem
-TextField
*Using ItemStateListener
*Multithreading
*RMS File Handling
-Sample Programs
*High Level UI, CommandListener, ItemStateListener
*Canvas, Multithreading
*RMS
-Additional
-Outro
INTRODUCTION:
Welcome to a starters overview on programming mobile phone applications in Java. This Java development uses a different edition of Java, Java 2 Micro Edition. If you have made other Java applications, it will most likely have been in the Standard Edition or Enterprise Edition. Info on getting the Micro Edition if you don't have it will be explained in the HOW TO START section, as well as how to get your programming environment up and running. This type of Java development can be used to create applications for many devices ranging from mobile phone, PDA’s, pagers, and any limited device that supports Java. If you’ve never used this type of development before, it might sound complicated, but it's actually surprisingly easy, made so by the API’s and development environment available to us. In this article (overview) I am only detailing the essential basics, such as drawing, interactions, controls, file handling etc, to get your J2ME programming up and running, and to give you an idea of what J2ME development is about, and hopefully both a nice starting place and future reference. This overview focuses on the coding aspect of J2ME development, information on setting up your device, or info on software to do with installing applications is not covered here.
USER REQUIREMENTS:
Before you start to program wireless device applications in Java, a moderate knowledge AT LEAST is required. Although this is quite easy, it’s not an outright beginner’s topic, if you have only just started to learn Java, head over to the java site http://java.sun.com/docs/books/tutorial/ and look at the great tutorials there, gain some experience and familiarity with the language and return when you feel you would like to see more on this type of Java development.
CONFIGURATIONS, PROFILES AND OPTIONAL PACKAGES:
Three things central to J2ME development are Configurations, Profiles and Optional Packages. These things basically define your Java environment, available API’s and the features of Java that you can use when writing applications for your device.
Java defines two Configurations: CLDC and CDC.
The CLDC (Connected Limited Device Configuration) and the CDC (Connected Device Configuration) contain a Java VM (Virtual Machine, usually the KVM for CLDC or CVM for CDC, although any VM adhering to the correct standards will work) to execute bytecode, to have the necessary native code to communicate specifically with the device it’s on, and a set of core classes. There aren’t many core classes defined in the configurations, so the functionality of the J2ME application relies on the additional classes defined in the various profiles and optional packages. The CLDC is the Configuration used for small devices, with little memory (i.e. Mobile Phones) and has a very small set of core classes, only the bare essentials. The CDC is used for more powerful and capable devices, including a fully-featured Java VM and a lot more core classes.
Profiles provide more device-specific classes, to add functionality to your application, such as User Interface (UI) classes. There are several profiles for J2ME development, for both configurations. For CLDC there is the MIDP (Mobile Information Device Profile) which was the original CLDC profile, and now the PDAP (Personal Digital Assistant Profile), which is like a tweaked / improved MIDP that comes in many varieties and is made for more powerful devices. For CDC there is the FP (Foundation Profile), which has more core classes from the Standard Edition of Java, the PBP (Personal Basis Profile) which extends the FP with more UI classes (from the Java 2 Standard Edition AWT Classes). Finally the PP (Personal Profile) adds to the PBP with more UI classes and applet support.
Optional packages provide even more functionality to your program by defining new sets of API’s that don’t really fit into any profile. Profiles may contain more specific API’s, but none of them are optional, i.e. if a device supports a profile, it must support everything defined within that profile. An API for Bluetooth, for example, would fit into the category of an optional package- simply because making it a part of a profile would limit that particular profile to only Bluetooth-enabled devices.
The most common Configuration for simple mobile phones is the CLDC, and the Profile MIDP, hence, this is what this article will cover.
HOW TO START:
Since this is a different type of Java Development, trying to build J2ME projects from your regular IDE might not work (unless it supports wireless development or you get a J2ME plug-in). The easiest way to build J2ME projects used to be with something called the Wireless Tool Kit, available for download from the Java site. You can now also just get the Java Platform Micro Edition Software Development Kit 3.0 [url=”http://java.sun.com/javame/downloads/sdk30.jsp”]J2ME SDK 3.0[/url]. If you have the old WTK program (before it was implemented into the SDK) get the 'ktoolbar.exe' program up and running, create a new project and the Toolkit will create all the necessary directories and files for you in it's apps directory, if you have the new J2ME SDK, simply run the main application, it's a fully featured IDE, so create a new project and you’re ready to go. When you create your project, you'll need to make sure you have the settings right- you need the correct MIDP and CLDC versions for your phone. You can set these by choosing the right target platform, and choosing the available options. If you create an application that’s ‘invalid’ when you try to run it on your device, then you are probably trying to use a version of CLDC or MIDP that your device doesn’t support. The J2ME SDK comes with many mobile phone emulators, simulating how your application will run under different phone model environments / constraints. Although this is nice and simple way to test your application, whilst your project / application is under development you should load it onto your device and test it under that environment often. Installing these applications on your phone can differ from model to model. Some phones you can simply drag and drop the .jar and the .jad files where you want them, some phones you can’t. You may want to see if you can get software from your device manufacturer, i.e. Nokia’s ‘Nokia PC Suite’. Some manufacturer software allows you to install your applications in different ‘environments’, this gives you application more or less freedom security-wise.
PORTABILITY
A very important issue with all developed applications is portability, and J2ME development is no different. Not only is there capability difference with this type of development (different MIDP / CLDC versions), there is also device-specific restrictions to take careful note of. These restrictions are things like screen size, amount of keypad buttons, types of buttons, graphical / audio capabilities etc. With these in mind, it is a lot easier to develop for a specific device model but this is not always an option. To create applications that are portable with a wider range of devices, you should be as general as possible . By this I mean that you reference specific details as little as possible. An example of this would be that if your mobile phone that you were creating an application for had a screen of about 200x200, and you wanted to draw (Low-Level UI) a proportioned rectangle of 20x20 (one tenth by one tenth), halfway from the top, and a quarter way from the left, rather than doing this:
CODE :
_____________________________________________________
//g is an object of Graphics
g.drawRect(50, 100, 20, 20); //x, y, width, height
_____________________________________________________
You should do something like this:
CODE :
____________________________________________________________________________
g.drawRect(this.getWidth()/4, this.getHeight()/2, this.getWidth ()/10, this.getHeight()/10);
____________________________________________________________________________
In this way, the scene would appear the same on different phone models of different screen sizes, because all the dimensions are adjusted to their environment. This same practice should be carried out as much as possible in all areas of your development. Another thing to consider is that the devices that you’re creating applications for are small / lightweight. I.e. they have little memory and for the most part a slower / lighter processor. For this reason, you must try to program in an efficient manner, so as to ensure your application works well with a range of different phone models. It’s very tempting to implement Runnable (use multithreading) for every class you have that extends Canvas, so you can keep up a constant repaint() (constantly update the screen). This coupled with other classes that rely upon multithreading can slow down your application or cause it to have a different performance on other phone models, so you should try to only use multithreading when it’s absolutely necessary.
PARTS OF A J2ME PROGRAM:
Just as you have Applications for the computer and Applets for the web, you have MIDlets for the wireless device. The entry point for your J2ME program must inherit (extend) MIDlet, but other classes you make don't have to. Like the Applet class, the MIDlet class is abstract, and so has required methods that any class inheriting MIDlet needs to override. These methods are:
CODE :
___________________________________________________________________________
public void startApp(){
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
___________________________________________________________________________
Putting this into perspective, a general MIDlet template would look like this (excluding user-interaction support / multithreading support / Any Display support, added in a nice, common, way to close application through exit()):
http://www.blogger.com/img/blank.gif
CODE :
_______________________________________________________________________
//File: MyMIDlet.java
import javax.microedition.midlet.*; //MIDlet
import javax.microedition.lcdui.*; //UI
public class MyMIDlet extends MIDlet
{
public MyMIDlet(){
}
public void startApp(){
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
private void exit() {
System.gc(); //Garbage Collect
destroyApp(false); //Run destroyApp method
notifyDestroyed(); //Let application know it’s now in destroyed //state
}
}
_______________________________________________________________________
All J2ME classes can be found in javax.microedition.*;
Classes that extend various other abstract J2ME classes (such as Canvas etc) will also have methods that will need to be overwritten.
Already you may notice a problem here- the main class needs to extend MIDlet, which means that it can’t inherit any other superclasses (although it can implement whatever it wants)- so what do we do when we want to draw to the screen and so on? The answer is simple, make different classes for the different ‘screens’ you wish your application to display at various times, have those classes extend the necessary superclass, and then to show them, simple transfer the display focus from the main MIDlet onto the class of the “screen” you wish to show. To transfer focus, the target must be a subclass of ‘Displayable’ (see Display Hierarchy in ADDITIONAL), i.e. a subclass of Screen, Canvas etc.
In the following example, the application enters at MyMIDlet, and then the MyMIDlet class transfers focus onto the MyCanvas class which fills the screen with white and draws a black string. In this way, the MyCanvas class is a ‘screen’, and you can quite easily make different classes to represent different ‘screens’ in your application and transfer focus between them whenever you wish. More on drawing and graphics will be covered in the DRAWING AND GRAPHICS section.
CODE :
__________________________________________________________________________
//File MyMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class MyMIDlet extends MIDlet
{
private Display display;
private MyCanvas canvas;
public MyMIDlet(){
display = Display.getDisplay(this);
canvas = new MyCanvas();
}
public void startApp(){
display.setCurrent(canvas);
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
}
//File MyCanvas.java
import javax.microedition.lcdui.*;
public class MyCanvas extends Canvas
{
public MyCanvas(){
}
public void paint(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(0x000000);
g.drawString(“You’re in MyCanvas!”, 20, 20, Graphics.LEFT | Graphics.TOP);
}
}
__________________________________________________________________________
A finished j2me application consists of two files, a .jar and a .jad. The .jar file holds all the classes, resources and the manifest file, whereas the .jad is a descriptor, i.e. it ‘describes’ the j2me application to the device that will run it. If you are not using an IDE, you will need to package all the necessary files into a jar, and create an appropriate .jad file. (Although it is a lot easier to let the IDE take care of this for you). Here is what a typical .jad file looks like:
CODE :
__________________________________________________________________________
MIDlet-1:, ,
MIDlet-Jar-Size:
MIDlet-Jar-URL:
MIDlet-Name:
MIDlet-Vendor:
MIDlet-Version:
MicroEdition-Configuration:
MicroEdition-Profile:
__________________________________________________________________________
To put this into perspective, here’s the current .jad file for my J2ME Sokoban game:
CODE :
__________________________________________________________________________
MIDlet-1: SokobanMain,/BOX1.png,SokobanMain
MIDlet-Jar-Size: 317218
MIDlet-Jar-URL: SOKOBANv2.jar
MIDlet-Name: SOKOBANv2
MIDlet-Vendor: ELJONTO
MIDlet-Version: 2.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-2.0
__________________________________________________________________________
Wrapping up parts of a J2ME application, you have the main entry class that inherits MIDlet and overrides all abstract methods, and then you have the other application classes who can transfer display focus between them if they are subclasses of Displayable.
DRAWING AND GRAPHICS
MIDlet’s have control over the screen through an object of Display. Each MIDlet can have only one Display object, and it is a superclass for Displayable. Display is used to represent the hardware for the display, whereas Displayable is used as a means of physically displaying something on the screen. Although there can be only one Display object for each MIDlet, there can be many objects of Displayable (because Displayable inherits Display, and all UI classes are beneath Displayable on the UI hierarchy, see Display Hierarchy in ADDITIONAL). This means, that every UI component, be it high level or low level inherits Displayable, and thus can be draw onto the device screen.
There exist two types of UI’s in J2ME, high level and low level. There are two direct subclasses of Displayable, Screen and Canvas. Screen is for high-level UI, and Canvas is for low-level UI. The difference between these is that Screen gives you access to pre-defined controls, such as text boxes, text fields- like the basic ones found in the Java SE awt packages. This gives you easy access to very powerful controls and UI components / elements which are very compatible with a large range of different devices. You can’t, however, draw directly to the screen. This is very limiting for most applications, especially games- where you need direct access to the screen to draw shapes etc. The ability to draw directly to the screen is done through the low-level UI classes of Canvas and Graphics. Canvas is an abstract class, where you need to overwrite the paint method. The paint method in your Canvas class is defined as follows:
CODE :
__________________________________________________________________________
public void paint(Graphics g){}
__________________________________________________________________________
This can be used in very much the same fashion as the paint method used in Java Applets, and through the Graphics object you can draw directly onto the screen of the device. There is also a subclass of Canvas called GameCanvas. This is like the regular Canvas class, but has been tweaked a bit for game development. It too, operates at a low level when it comes to drawing and graphics. The GameCanvas class will be discussed in a later article. The default origin (0,0) when drawing to the screen is at the top left of the device screen. Some drawing methods in Graphics take an integer alignment as a parameter (e.g drawString(), drawImage()). The options you have are:
Graphics.LEFT,
Graphics.RIGHT,
Graphics.TOP,
Graphics.BOTTOM,
Graphics.HCENTER,
Graphics.VCENTER,
Graphics.BASELINE.
These are OR’d together to give the alignment position of what you want to draw. I.e., to specify an image should be drawn in the middle of the screen, in the middle of the image:
CODE :
__________________________________________________________________________
//g is an object of Graphics
g.drawImage(image, this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
__________________________________________________________________________
If you’ve ever programmed a Java Applet before (Very unlikely that you haven’t if you’re reading this), then you’ll know that mixing the controls (text fields, text areas, buttons, etc) in the awt packages and drawing directly to the Applet from the paint method work together without any problems. In J2ME development, this is not the case. High-level UI and Low-level UI can’t mix, different ‘screens’ in your application can use different UI levels, but display must be transferred between them, it can’t be on both levels at the same time.
FILE HANDLING:
There are two types of data / file handling in J2ME, the first is like regular data / file handling on your computer, where you open a path, browse directories etc. This is done with the FileConnection API. A large part of Java development is security, therefore, having any application being able to read / write data / files natively on the device would be a huge security risk. This is where problems arise, unless your application is trusted, this type of file handling might request a response from the user every time it tries to read / write data to the file system, and some phone models might not allow it at all. These restrictions are unnecessary if all you want your program to do is save some options, game highs scores, unlocked levels etc. This brings us to the second type of file / data handling, persistent, through the RMS (Record Management Store) API. The RMS reads / writes data through a file / database crossover. Each MIDlet can have any number of RecordStores, and in MIDP version 2.0 MIDlet’s can access other MIDlet’s RecordStores (not discussed in this overview). All data inside the RecordStores are saved as Records, every Record is an array of bytes, and each record has an integer identifier. The RecordStores are protected from corruption by features like automatic synchronization etc, however it is still up to you to control access to the RecordStores in your application. This article will only detail using the RMS method of data / file handling because in most situations, the MIDlet needs to be signed to use the FileConnection API, or be installed in a trusted environment.
PROGRAM ACTION AND INTERACTION
Here I’ll explain how do to the various things in your J2ME application, such as drawing, handling events etc, and in SAMPLE PROGRAMS you can see these concepts as completed demo applications, with complete source code. I am not going to explain every member method for everything I describe here, some are self-explanatory, some you might need to look up, but this section is not a complete reference.
== Catching Keys:
Listening and catching keys (Not commands) in J2ME is done through the low-level UI classes of Canvas or GameCanvas, via the methods:
CODE :
__________________________________________________________________________
protected void keyPressed(int keyCode){}
protected void keyReleased(int keyCode){}
__________________________________________________________________________
Where keyCode is the code of the key that has been pressed / released. Key Catching in high-level UI is either handled automatically by the control, or done by catching the softkeys (More on softkeys in next subsection).
If you are creating your own low-level UI controls (e.g. a custom text field) that uses user input via the keypad, the keyCode for keys 0-9 will be the ASCII equivalents (48 - 57) so casting to char ((char)keyCode) will give you the number pressed. The other, non-keypad buttons have a negative keyCode, some of these values can be found here: http://www.j2meforums.com/wiki/index.php/Canvas_Keycodes .
If the Canvas that’s catching keys is being used for a game, using keyCode directly can be annoying, so instead we can use the method getGameAction(), and then choose from the list of statics in javax.microedition.lcdui.Canvas;
Example:
CODE :
__________________________________________________________________________
//Without using getGameAction()
protected void keyPressed(int keyCode){
if(keyCode == -1){
//Up Pressed
}else if(keyCode == -2){
//Down Pressed
}else if(keyCode == -3){
//Left Pressed
}else if(keyCode == -4){
//Right Pressed
}
}
//Using getGameAction()
protected void keyPressed(int keyCode){
int gameAction = getGameAction(keyCode);
if(gameAction == UP){
//Up Pressed
}else if(gameAction == DOWN){
//Down Pressed
}else if(gameAction == LEFT){
//Left Pressed
}else if(gameAction == RIGHT){
//Right Pressed
}
}
__________________________________________________________________________
The statics in javax.microedition.lcdui.Canvas that you can use are:
DOWN, FIRE, GAME_A, GAME_B, GAME_C, GAME_D, KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8, KEY_NUM9, KEY_POUND, KEY_STAR, LEFT, RIGHT, UP
== Using CommandListener and Soft Keys
Soft Keys are the keys that aren’t part of the numpad, they’re usually situated above the numpad, but underneath the screen (on a typical mobile phone). They are keys such as the navigation joystick, the answer call / hang-up call/ select button etc. You may have noticed that it’s impossible in most case to get control of these for use in your application through the low-level UI key catching methods. There’s a reason for this, these are Command buttons. The other buttons, such as a 0 on the numpad, will always be and represent a 0 on the numpad (in this example). These Command buttons, however, can represent anything you want, from an Exit button, to a Select button, an Options button etc. Another reason is that these must be available to both high and low level UI implementations, and the keyPressed() and keyReleased() methods are a part of Canvas, low level UI.
To make use of these keys, you need to implement the interface CommandListener, and control the actions through:
CODE :
__________________________________________________________________________
public void commandAction(Command c, Displayable d){}
__________________________________________________________________________
Where “Command c” is the activated command and “Displayable d” is the Displayable object that activated the command. The class that implements CommandListener and hence has the method commandAction() can control the commands of any Displayable object as long the commandListener for the said object is set to the class implement CommandAction. This means that it is possible to have only one class implementing CommandListener, which controls all commands of all Displayable objects (Canvas, GameCanvas, Form, List etc).
To catch softkeys, you need to create a Command object for each command you want, add the Command objects to the displayable object you want the commands on, and set the commandListener of the displayable object to a CommandListener implementation that has the commandAction() method.
An example of usage, complete code will be in SAMPLE PROGRAMS section:
CODE :
__________________________________________________________________________
private MyCanvasClass mycanvas;
private Command exitCmd;
…
display = Display.getDisplay(this);
mycanvas = new MyCanvasClass();
exitCmd = new Command(“exit”, Command.EXIT, 0);
…
mycanvas.addCommand(exitCmd);
mycanvas.setCommandListener(this);
display.setCurrent(mycanvas);
…
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
__________________________________________________________________________
The Command constructor takes three parameters, the first being a label, String with the text the command will show. The second being a type, one of:
Command.BACK
Command.CANCEL
Command.EXIT
Command.HELP
Command.ITEM
Command.OK
Command.SCREEN
Command.STOP
The third parameter taken is an Integer priority. The Type and Priority parameters are how you can tell your device which commands should be assigned to what soft keys. For example on my current phone, the Nokia 6300, the command with the highest priority gets assigned to the center soft key, and commands of type Command.EXIT get assigned to the left soft key at the bottom of the screen. If there are more commands than soft keys available, a pop-up menu is automatically created on one of the soft keys, allowing the user to choose the other commands. Note that the command / soft key assignment is different on different devices.
== Predefined Controls and High Level UI Elements
Just like there exist UI controls for you to use in the java applet awt packages, there also exist similar controls in the J2ME lcdui packages. These UI controls are High level UI, because they are below the Screen class on the Display hierarchy (Display Hierarchy in ADDITIONAL), and cannot be mixed with low level UI access, as I mentioned earlier. Because these controls are High-level UI, you have very limited access when it comes to displaying them. This makes them very portable and a good option for creating an interface for the user to input data, but a bad option for game development, or any application where you’d like to have full control over the screen and appearances.
On the High-Level UI hierarchy directly underneath Screen are the classes Alert, List, TextBox and Form. All of these use the whole display. The ‘Ticker’ control, however, isn’t a control; it’s a variable in the Screen class.
-Alert
An Alert is essentially a very simple dialog box. It can have text, pictures and a sound warning. Alerts can either run until the user acknowledges it, or it can run for a pre-determined amount of time. When an alert finishes it will return focus to the last Displayable object that held focus (I.E. the Displayable object that ‘called’ it). However, if you want to transfer focus to a different displayable object when the alert finishes, add the other Displayable object as a parameter to setCurrent(); like so:
CODE :
__________________________________________________________________________
display.setCurrent(alert, newdisplayableobject);
__________________________________________________________________________
Creating a new Alert object:
CODE :
__________________________________________________________________________
Alert alert = new Alert("Alert Title Text", "Alert body text", alertImage, alertType);
__________________________________________________________________________
alertType is a static from the AlertType class, it is a sound for the alert and can be: AlertType.ALARM, AlertType.CONFIRMATION, AlertType.ERROR, AlertType.INFO, AlertType.WARNING.
The setTimeout method will set the amount of time in milliseconds that the alert will stay active.
CODE :
__________________________________________________________________________
alert.setTimeout(2000); //2 seconds
__________________________________________________________________________
If you want the alert to remain until the user acknowledges it, use the static FOREVER
CODE :
__________________________________________________________________________
alert.setTimeout(Alert.FOREVER);
__________________________________________________________________________
If an Alert is set to Alert.FOREVER and you don’t add any commands and don’t set a commandListener onto an Alert object, it will have a ‘done’ option by default, however if you do, you will need to define all commands.
-List
A list can present a series of choices, accompanied with images, for the user to choose (I.E. a menu). A List can be MULTIPLE / EXCLUSIVE, making it effectively a full-screen ChoiceGroup (discussed later), but benefits most as a menu if it is IMPLICIT.
Creating a list object:
CODE :
__________________________________________________________________________
List list = new List(“List Title”, List.IMPLICIT, listOptions, listImages);
__________________________________________________________________________
Where listOptions is a String array containing menu options and listImages is an Image array containing Images corresponding to the options.
If you don’t want to include any images, set the parameter to null.
To find out which option(s) are selected you can use:
CODE :
__________________________________________________________________________
list.getSelectedIndex();
__________________________________________________________________________
However, if you are using an IMPLICIT list, and have set a command listener onto it you can use this in your commandAction() method:
CODE :
__________________________________________________________________________
public void commandAction(Command c, Displayable d){
if(c == List.SELECT_COMMAND){
switch(list.getSelectedIndex()){
case n:
//etc
break;
default:
break;
}
}
}
__________________________________________________________________________
-TextBox
A TextBox is a multi-line control which allows users to enter text.
Create a TextBox object:
CODE :
__________________________________________________________________________
TextBox txtBox = new TextBox(“TextBox title”, “Text inside of textbox”, charlimit, restrictions);
__________________________________________________________________________
Where ‘charlimit’ is an integer which defines the max amount of characters that can be entered, and ‘restrictions’ is a static int from the TextField class, which defines the type of text that can be entered. The Options are: ANY, NUMERIC, PASSWORD, PHONENUMBER, EMAILADDR, and URL.
Use the OR operator to combine these:
CODE :
__________________________________________________________________________
TextField.EMAILADDR | TextField.PASSWORD
__________________________________________________________________________
This would only accept a valid email address and it would mask the input like a password field.
*Note: If you are having text inside of a TextBox, make sure it doesn’t exceed the charlimit you set; otherwise an IllegalArgumentException will be thrown.
-Ticker
A Ticker is a little banner of scrolling text (like HTML marquee, you know, the scrolling text that you see advertising stuff on crappy websites) at the top of a direct descendant of Screen (Alert, TextBox, List, and Form). Ticker is not a child of Screen; it is a variable, which is why it can be displayed on Screen children.
Create a new Ticker object:
CODE :
__________________________________________________________________________
Ticker tckr = new Ticker("A ticker, not a control- a variable of Screen");
__________________________________________________________________________
To add a Ticker object to a direct Screen child use the method:
CODE :
__________________________________________________________________________
screenchild.setTicker(tickerobject);
__________________________________________________________________________
-Form
A Form is a direct child of Screen that can hold all typical UI controls. These controls are of superclass Item (ChoiceGroup, CustomItem, DateField, Gauge, ImageItem, Spacer, StringItem, and TextField) see the Display Hierarchy in ADDITIONAL. Like the other direct children of Screen, Form uses the whole display, but unlike the others (except List) it will scroll to accommodate the Item’s it houses. A Form is arranged in “rows”, and it will try to put as many controls as it can onto each row. With small-screened devices, usually only one control fits per row. If your device can fit more than one control per row, to tidy up the layout you can use Spacers (discussed later) and the layout options in Item.
Create a form object:
CODE :
__________________________________________________________________________
Form frm = new Form(“Form Title”);
__________________________________________________________________________
Once you have created a form object, you add Item’s onto it using the append method
CODE :
__________________________________________________________________________
frm.append(item);
[code]
Every Item on a form can have a layout, set with the method:
[code]
setLayout(int layout);
__________________________________________________________________________
where layout can be:
Item.LAYOUT_2, Item.LAYOUT_BOTTOM, Item.LAYOUT_CENTER, Item.LAYOUT_DEFAULT, Item.LAYOUT_EXPAND, Item.LAYOUT_LEFT, Item.LAYOUT_NEWLINE_AFTER, Item.LAYOUT_NEWLINE_BEFORE, LAYOUT_RIGHT, Item.LAYOUT_SHRINK, Item.LAYOUT_TOP, Item.LAYOUT_VCENTER, Item.LAYOUT_VEXPAND, Item.LAYOUT_VSHRINK.
Since Form is Displayable, it too can have commands, command listeners etc
Following are descriptions of the controls that can appear on a form:
-ChoiceGroup
The ChoiceGroup control is like a list, it presents the user with a selection to choose from. There are two types of ChoiceGroup, multiple-selection (checkbox) and exclusive-selection (radio-group).
Create a ChoiceGroup object:
CODE :
__________________________________________________________________________
ChoiceGroup cg = new ChoiceGroup(“ChoiceGroup title”, type);
__________________________________________________________________________
Or create a ChoiceGroup object with options / images:
CODE :
__________________________________________________________________________
ChoiceGroup cg = new ChoiceGroup(“ChoiceGroup title”, type, options, images);
__________________________________________________________________________
Where type is either ChoiceGroup.MULTIPLE or ChoiceGroup.EXCLUSIVE, options is a String array containing the choices and images are the corresponding images to accompany the choices. Use null for the image parameter if you aren’t having any images.
To add an option to your ChoiceGroup object:
CODE :
__________________________________________________________________________
cg.append(“option”, image);
Where image is the accompanying image, otherwise use null.
To get the selected options you can use:
CODE :
getSelectedIndex();
__________________________________________________________________________
Or to return a boolean array of the selected / unselected:
CODE :
__________________________________________________________________________
getSelectedFlags(returnArray);
__________________________________________________________________________
Where returnArray is a boolean array.
-CustomItem
A CustomItem lets you define your own Item to place on a form. To create a new CustomItem, create a class for your control, have it extend CustomItem. The CustomItem constructor requires a String title, and since it’s abstract you need to use a few methods. This leaves the shell of a CustomItem subclass looking like:
CODE :
__________________________________________________________________________
class MyItem extends CustomItem
{
public MyItem(String title){
super(title);
}
protected int getMinContentHeight() {}
protected int getMinContentWidth() {}
protected int getPrefContentHeight(int width) {}
protected int getPrefContentWidth(int height) {}
protected void paint(Graphics g, int w, int h) {}
}
__________________________________________________________________________
If we were to finish our MyItem (This will be covered in a later article), using it would be the same as the other Items:
CODE :
__________________________________________________________________________
MyItem myItem = new MyItem(“My Custom Item”);
form.append(myItem);
__________________________________________________________________________
-DateField
A DateField Item lets you view / change the date and time.
Creating a DateField object:
CODE :
__________________________________________________________________________
DateField df = new DateField(“Title”, type);
DateField df = new DateField(“Title”, type, timezone);
__________________________________________________________________________
Where type is either DateField.DATE, DateField.TIME, DateField.DATE_TIME, allowing the user to edit the date, the time, or both (respectively). The timezone parameter is an object of TimeZone.
You can set / get the date using:
CODE :
__________________________________________________________________________
df.setDate(date);
Date date = df.getDate();
__________________________________________________________________________
Where Date is defined in the java.util package.
-Gauge
A gauge is meter that displays the progress of something. It’s typically used to show the volume level when adjusting, however if can be used for whatever you want. You can have an interactive gauge (I.E. volume control), or a non-interactive gauge where the application itself must change the value.
Creating a gauge object:
CODE :
__________________________________________________________________________
Gauge gauge = new Gauge(“Title”, interactive, maxvalue, startvalue);
__________________________________________________________________________
Where interactive is a boolean, true: interactive, false: non interactive, maxvalue is an integer for the maximum value of the gauge and startvalue is the value the gauge should start at.
To get / set the value of a Gauge object:
CODE :
__________________________________________________________________________
gauge.setValue(integervalue);
int value = gauge.getValue();
__________________________________________________________________________
-ImageItem
An ImageItem lets you put an image onto a form.
Create and ImageItem object:
CODE :
__________________________________________________________________________
ImageItem imageItem = new ImageItem(“Title”, image, layout, “Alt text”);
__________________________________________________________________________
Where image is an object of type Image, layout is any of the LAYOUT statics in Item (mentioned above in –Form section).
You can create an Image Object using Image.createImage(). This method is overridden quite a few times, but the easiest way takes only a String path to an image file:
CODE :
__________________________________________________________________________
Image.createImage(String imagePath);
__________________________________________________________________________
-Spacer
A Spacer is simply a section of white space that you can size accordingly and use to put some extra ‘space’ into your form to help with layout.
Create a Spacer object:
CODE :
__________________________________________________________________________
Spacer spcr = new Spacer(horizPadding, vertPadding);
__________________________________________________________________________
Where horizPadding is an integer value for the horizontal white space and vertPadding is an integer value for the vertical white space.
Simply append the Spacer object to the form wherever you want the white space.
-StringItem
A StringItem is simply a label control to put text onto a form.
Create a StringItem object:
CODE :
__________________________________________________________________________
StringItem str = new StringItem(“Title”, “Your Text”);
__________________________________________________________________________
Alternatively, you can add text onto a form by simply appending a String:
CODE :
__________________________________________________________________________
form.append(“Text to put on form”);
__________________________________________________________________________
The reason there exists a StringItem class when you can use the above method is so that you can get / set the text etc.
CODE :
__________________________________________________________________________
String recvStr = str.getText();
Str.setText(“New Text”);
__________________________________________________________________________
-TextField
A TextField is a single-line TextBox control, which allows the user to enter the type of text allowed. TextBox shares the same text restrictions as TextField, which are: TextField.ANY, TextField.NUMERIC, TextField.PASSWORD, TextField.PHONENUMBER, TextField.EMAILADDR, and TextField.URL. Look up the TextBox section for more on using these restrictions.
Create a TextField object:
CODE :
__________________________________________________________________________
TextField txt = new TextField(“Title”, “Text in box”, charlimit, restrictions);
__________________________________________________________________________
Where charlimit is an integer to represent the max allowed characters (make sure if you have text inside the text field on initialisation that it doesn’t exceed the limit) and restrictions is an integer for a static restriction from the TextField class (discussed above).
== Using ItemStateListener
Where CommandListener is triggered on interaction with commands, ItemStateListener is triggered on interaction with controls. Using ItemStateListener is very similar to using CommandListener (discussed earlier). The class that’s going to listen for state changes will need to implement ItemStateListener, and then override the method:
CODE :
__________________________________________________________________________
public void itemStateChanged(Item i){}
__________________________________________________________________________
To set up a Displayable object to listen for state changes, use the method:
CODE :
__________________________________________________________________________
displayableObj.setItemStateListener(listener);
__________________________________________________________________________
where listener is the class that implements ItemStateListener, and hence has the itemStateChanged() method.
An example of usage is shown in SAMPLE PROGRAMS.
== Multithreading
There’s nothing special to multithreading in J2ME development, it can be used by inheriting Thread or implementing Runnable. J2ME classes that serve a UI purpose usually inherit a class (Canvas, GameCanvas etc) so it’s generally easier to use the implementation method. Multithreading should be used as little as possible in this type of development, bearing in mind the type of processor the destined device has. Obviously there are some situations where it’s absolutely necessary, such as updating a game screen, but it’s important to not go overboard. To limit multithreading in your J2ME application, you may need to reorganise your code a bit, so that you end up having one class with multithreaded support, updating the activities of the other classes that would have normally been multithreaded. In many situations this might not be preferable, but just try to use it as little as possible.
== RMS File Handling
See FILE HANDLING for an explanation of RMS.
The import:
CODE :
__________________________________________________________________________
import javax.microedition.rms.*;
Create / Open a RecordStore:
CODE :
__________________________________________________________________________
RecordStore recStore = RecordStore.openRecordStore(name, createIfDoesntExist);
__________________________________________________________________________
Where name is the String name of the RecordStore and createIfDoesntExist is a boolean variable, true to create the RecordStore if it doesn’t exist, if it does exist, the RecordStore will be opened. False to not create the RecordStore if it doesn’t exist, if it does exist, the RecordStore will be opened.
Delete a RecordStore:
CODE :
__________________________________________________________________________
RecordStore.deleteRecordStore(name);
__________________________________________________________________________
Where name is the String name of the RecordStore to delete.
Close a RecordStore:
CODE :
__________________________________________________________________________
recStore.closeRecordStore();
__________________________________________________________________________
Add a Record:
CODE :
__________________________________________________________________________
recStore.addRecord(data, offset, bytesAmount);
__________________________________________________________________________
Where data is a byte array, offset is where you want to start writing to in the Record and bytesAmount is the number of bytes from data you want written. The addRecord() method returns the ID of the record you added.
Set / Overwrite a Record:
CODE :
__________________________________________________________________________
recStore.setRecord(recID, data, offset, bytesAmount);
__________________________________________________________________________
Same as the addRecord() method, only you need to include the recID parameter, which is the integer ID of the Record you want to overwrite.
Delete a Record:
CODE :
__________________________________________________________________________
recStore.deleteRecord(recID);
__________________________________________________________________________
Where recID is the integer ID of the Record you want to delete.
Get a Record:
CODE :
__________________________________________________________________________
byte[] data = recStore.getRecord(recID);
//OR
recStore.getRecord(recID, data, offset);
__________________________________________________________________________
Where recID is the Integer ID of the Record you want, data is a byte[] array to hold the bytes and offset is an Integer offset to say where to start reading from.
SAMPLE PROGRAMS:
Here are three, ready-to-compile and run J2ME applications, that use most of what is described or presented in this article. The first will display the High-Level UI, some controls, and using the Listeners, the second- the Low Level UI with Multithreading and the last, the RMS file handling / database emulating system. When I say ‘application’, I am not referring to something built to solve a problem, hell, or even be useful- these are just a compilation of some of the things shown here so you can see them work, and to give you an idea of how to implement them.
== High Level UI, CommandListener, ItemStateListener
CODE :
__________________________________________________________________________
//File: DemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class DemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private ListDemo listDemo;
private TextBoxDemo textBoxDemo;
private FormDemo formDemo;
private AlertDemo alertDemo;
private Command exitCmd, menuCmd;
public DemoMIDlet(){
display = Display.getDisplay(this);
listDemo = new ListDemo("A List Menu", List.IMPLICIT, new String[]{"TextBox", "Form", "Alert"}, null);
textBoxDemo = new TextBoxDemo("A TextBox", "Stuff inside textBox, 500 char limit, ANY text", 500, TextField.ANY);
formDemo = new FormDemo("A Form");
alertDemo = new AlertDemo("An INFO Alert", "Alert content", null, AlertType.INFO);
exitCmd = new Command("Exit", Command.EXIT, 0);
menuCmd = new Command("Menu", Command.BACK, 1);
}
public void startApp() {
listDemo.addCommand(exitCmd);
listDemo.setCommandListener(this);
textBoxDemo.addCommand(exitCmd);
textBoxDemo.addCommand(menuCmd);
textBoxDemo.setCommandListener(this);
formDemo.addCommand(exitCmd);
formDemo.addCommand(menuCmd);
formDemo.setCommandListener(this);
display.setCurrent(listDemo);
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
private void exit() {
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}else if(c == menuCmd){
display.setCurrent(listDemo);
}else if(c == List.SELECT_COMMAND && d == listDemo){
switch(listDemo.getSelectedIndex()){
case 0:
display.setCurrent(textBoxDemo);
break;
case 1:
display.setCurrent(formDemo);
break;
case 2:
display.setCurrent(alertDemo);
break;
default:
break;
}
}
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: ListDemo.java
import javax.microedition.lcdui.*;
public class ListDemo extends List
{
public ListDemo(String title, int TYPE, String[] options, Image[] images){
super(title, TYPE, options, images);
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: TextBoxDemo.java
import javax.microedition.lcdui.*;
public class TextBoxDemo extends TextBox
{
public TextBoxDemo(String title, String content, int MAXSIZE, int TYPE){
super(title, content, MAXSIZE, TYPE);
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: FormDemo.java
/*
* Make sure you comment out the ImageItem parts if you don’t supply an image
*/
import java.io.IOException;
import javax.microedition.lcdui.*;
public class FormDemo extends Form implements ItemStateListener
{
private Ticker tckr;
private DateField df;
private StringItem str;
private Gauge gauge;
private Spacer spcr;
private TextField txt;
private ChoiceGroup cg;
private ImageItem imgItem;
public FormDemo(String title){
super(title);
tckr = new Ticker("A ticker, not a control- part of Screen");
df = new DateField("A Date Field control", DateField.DATE_TIME);
str = new StringItem("stritem", "TEXT");
gauge = new Gauge("Volume Gauge", true, 10, 6);
try{
imgItem = new ImageItem("An Image", Image.createImage("/image.png"), ImageItem.LAYOUT_DEFAULT, "Alternate text");
}catch(IOException e){}
spcr = new Spacer(0,40);
txt = new TextField("TextField", "Enter Text", 20, TextField.ANY);
cg = new ChoiceGroup("ChoiceGroup", ChoiceGroup.MULTIPLE);
cg.append("Choice 1", null);
cg.append("Choice 2", null);
this.setTicker(tckr);
this.append(df);
this.append(str);
this.append("String Message 2!");
this.append(spcr);
this.append(gauge);
this.append(txt);
this.append(cg);
this.append(imgItem);
this.setItemStateListener(this);
}
public void itemStateChanged(Item i){
str.setText(i.getLabel()+" has changed");
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: AlertDemo.java
import javax.microedition.lcdui.*;
public class AlertDemo extends Alert
{
public AlertDemo(String title, String content, Image image, AlertType TYPE){
super(title, content, image, TYPE);
}
}
== Canvas / Multithreading
CODE :
//File: DemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class DemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private CanvasDemo canvas;
private Command exitCmd;
public DemoMIDlet(){
display = Display.getDisplay(this);
canvas = new CanvasDemo();
exitCmd = new Command("Exit", Command.EXIT, 0);
}
public void startApp() {
canvas.addCommand(exitCmd);
canvas.setCommandListener(this);
display.setCurrent(canvas);
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) {
}
private void exit() {
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: CanvasDemo.java
import java.io.IOException;
import javax.microedition.lcdui.*;
public class CanvasDemo extends Canvas implements Runnable{
private Thread MainThread;
private long sleep = 50;
private boolean run = true;
private String keyAction = "Key";
private Image img;
private int[] moveShapeLoc = {
this.getWidth()/10,
this.getWidth()/4,
this.getHeight()/8
};
private int[] autoShapeDim = {
this.getWidth()/2,
this.getHeight()/2,
this.getWidth()/10,
this.getHeight()/10,
};
private int direction;
private static int DIRECTIONLEFT = 0;
private static int DIRECTIONRIGHT = 1;
public CanvasDemo(){
MainThread = new Thread(this);
try{
img = Image.createImage("/image.png");
}catch(IOException e){}
direction = DIRECTIONRIGHT;
MainThread.start();
}
public void run(){
while(run){
autoShape();
repaint();
try{
Thread.sleep(sleep);
}catch(InterruptedException e){}
}
}
protected void keyPressed(int keyCode){
int gameAction = getGameAction(keyCode);
keyAction = "Key Down: (int)"+keyCode;
if(gameAction == LEFT){
moveShape(-4, 0);
}else if(gameAction == RIGHT){
moveShape(4, 0);
}else if(gameAction == UP){
moveShape(0, -4);
}else if(gameAction == DOWN){
moveShape(0, 4);
}
}
protected void keyReleased(int keyCode){
int gameAction = getGameAction(keyCode);
keyAction = "Key Up: (int)"+keyCode;
}
private void moveShape(int hspeed, int vspeed){
moveShapeLoc[1] += hspeed;
moveShapeLoc[2] += vspeed;
}
private void autoShape(){
if(direction == DIRECTIONLEFT){
if(autoShapeDim[0] > 0){
autoShapeDim[0]--;
}else{
direction++;
}
}else{
if(autoShapeDim[0] + autoShapeDim[2] < this.getWidth()){
autoShapeDim[0]++;
}else{
direction--;
}
}
}
public void paint(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(0x000000);
g.drawString("CanvasDemo", 1, 1, Graphics.LEFT | Graphics.TOP);
g.drawString(keyAction, 1, 20, Graphics.LEFT | Graphics.TOP);
g.fillRect(autoShapeDim[0], autoShapeDim[1],autoShapeDim[2],autoShapeDim[3]);
g.setColor(0xFF0000);
g.drawArc(moveShapeLoc[1], moveShapeLoc[2], moveShapeLoc[0]*2, moveShapeLoc[0]*2, 0, 360);
g.drawImage(img, this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
}
}
== RMS
CODE :
__________________________________________________________________________
//File: RMSDemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
public class RMSDemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private Form form;
private StringItem progress;
private Command exitCmd;
public RMSDemoMIDlet(){
display = Display.getDisplay(this);
form = new Form("RMS Demo");
progress = new StringItem("Progress:", "");
exitCmd = new Command("Exit", Command.EXIT, 0);
}
public void startApp() {
form.append(progress);
form.addCommand(exitCmd);
form.setCommandListener(this);
rmsDemo();
display.setCurrent(form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
private void exit(){
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
private void rmsDemo(){
progress.setText(progress.getText() + "\n>>Attempting to create RecordStore 'RecStore'");
RecordStore rs = null;
try{
rs = RecordStore.openRecordStore("RecStore", true);
progress.setText(progress.getText() + "\n>>Created RecordStore");
progress.setText(progress.getText() + "\n>>Attempting to add records");
String[] records = {
"The first record",
"The second record",
"The third record",
"The fourth record",
};
for(int i = 0; i < records.length; i++){
rs.addRecord(records[i].getBytes(), 0, records[i].length());
}
progress.setText(progress.getText() + "\n>>Added records");
progress.setText(progress.getText() + "\n>>Attempting to read records: ");
for(int i = 1; i <= rs.getNumRecords(); i++){
progress.setText(progress.getText() + "\n");
for(int j = 0; j < rs.getRecord(i).length; j++){
progress.setText(progress.getText() + (char)(rs.getRecord(i)[j]));
}
}
progress.setText(progress.getText() + "\n");
progress.setText(progress.getText() + "\n>>Attempting to edit records");
for(int i = 1; i <= rs.getNumRecords(); i++){
String newData = records[i-1]+" edited";
rs.setRecord(i, newData.getBytes(), 0, newData.length());
}
progress.setText(progress.getText() + "\n>>Attempting to read new records: ");
for(int i = 1; i <= rs.getNumRecords(); i++){
progress.setText(progress.getText() + "\n");
for(int j = 0; j < rs.getRecord(i).length; j++){
progress.setText(progress.getText() + (char)(rs.getRecord(i)[j]));
}
}
progress.setText(progress.getText() + "\n");
progress.setText(progress.getText() + "\n>>Attempting to delete records");
for(int i = 1; i <= rs.getNumRecords(); i++){
rs.deleteRecord(i);
}
progress.setText(progress.getText() + "\n>>Deleted records");
progress.setText(progress.getText() + "\n>>Attempting to close RecordStore 'RecStore'");
rs.closeRecordStore();
progress.setText(progress.getText() + "\n>>RecordStore closed");
progress.setText(progress.getText() + "\n>>Attempting to delete RecordStore 'RecStore'");
RecordStore.deleteRecordStore("RecStore");
progress.setText(progress.getText() + "\n>>RecordStore deleted");
}catch(RecordStoreException e){
progress.setText(progress.getText() + "\n>>Fail: "+e.getMessage());
}
}
}
__________________________________________________________________________
ADDITIONAL
==Display Hierarchy:
Display
|
Displayable
| |
| Canvas
|
Screen
|
Form, List, Alert, TextBox
|
Item
|
ChoiceGroup, CustomItem, DateField, Gauge, ImageItem, Spacer, StringItem, TextField
OUTRO:
Well, that concludes my basic overview on coding with J2ME with the focus on mobile phone application development. I hope that you have found this useful, and all feedback (comments / suggestions / corrections) is very welcome. Feel free to contact me (eljonto {AT} live {DOT} com) if you have any questions, I’ll do my best to answer them. If I get around to writing more articles on J2ME, it will cover more areas, and revisit areas in depth (Such as Canvas, GameCanvas, etc), as this overview isn’t very comprehensive in many areas, if it was- it wouldn’t be a basic overview.
source : http://www.hackthissite.org/
| Programming Mobile Phone Applications in Java |
| OVERVIEW |
| |
| Author: ELJONTO (eljonto@live.com) |
|_______________________________________________|
*NOTE: The original content / code IS nicely indented…
CONTENTS:
-Introduction
-User Requirements
-Configurations, Profiles and Optional Packages
-How to start
-Portability
-Parts of a J2ME program
-Drawing and Graphics
-File Handling
-Program Action and Interaction
*Catching keys
*Using CommandListener & softkeys
*Predefined controls and High Level UI elements
-Alert
-List
-TextBox
-Ticker
-Form
-ChoiceGroup
-CustomItem
-DateField
-Gauge
-ImageItem
-Spacer
-StringItem
-TextField
*Using ItemStateListener
*Multithreading
*RMS File Handling
-Sample Programs
*High Level UI, CommandListener, ItemStateListener
*Canvas, Multithreading
*RMS
-Additional
-Outro
INTRODUCTION:
Welcome to a starters overview on programming mobile phone applications in Java. This Java development uses a different edition of Java, Java 2 Micro Edition. If you have made other Java applications, it will most likely have been in the Standard Edition or Enterprise Edition. Info on getting the Micro Edition if you don't have it will be explained in the HOW TO START section, as well as how to get your programming environment up and running. This type of Java development can be used to create applications for many devices ranging from mobile phone, PDA’s, pagers, and any limited device that supports Java. If you’ve never used this type of development before, it might sound complicated, but it's actually surprisingly easy, made so by the API’s and development environment available to us. In this article (overview) I am only detailing the essential basics, such as drawing, interactions, controls, file handling etc, to get your J2ME programming up and running, and to give you an idea of what J2ME development is about, and hopefully both a nice starting place and future reference. This overview focuses on the coding aspect of J2ME development, information on setting up your device, or info on software to do with installing applications is not covered here.
USER REQUIREMENTS:
Before you start to program wireless device applications in Java, a moderate knowledge AT LEAST is required. Although this is quite easy, it’s not an outright beginner’s topic, if you have only just started to learn Java, head over to the java site http://java.sun.com/docs/books/tutorial/ and look at the great tutorials there, gain some experience and familiarity with the language and return when you feel you would like to see more on this type of Java development.
CONFIGURATIONS, PROFILES AND OPTIONAL PACKAGES:
Three things central to J2ME development are Configurations, Profiles and Optional Packages. These things basically define your Java environment, available API’s and the features of Java that you can use when writing applications for your device.
Java defines two Configurations: CLDC and CDC.
The CLDC (Connected Limited Device Configuration) and the CDC (Connected Device Configuration) contain a Java VM (Virtual Machine, usually the KVM for CLDC or CVM for CDC, although any VM adhering to the correct standards will work) to execute bytecode, to have the necessary native code to communicate specifically with the device it’s on, and a set of core classes. There aren’t many core classes defined in the configurations, so the functionality of the J2ME application relies on the additional classes defined in the various profiles and optional packages. The CLDC is the Configuration used for small devices, with little memory (i.e. Mobile Phones) and has a very small set of core classes, only the bare essentials. The CDC is used for more powerful and capable devices, including a fully-featured Java VM and a lot more core classes.
Profiles provide more device-specific classes, to add functionality to your application, such as User Interface (UI) classes. There are several profiles for J2ME development, for both configurations. For CLDC there is the MIDP (Mobile Information Device Profile) which was the original CLDC profile, and now the PDAP (Personal Digital Assistant Profile), which is like a tweaked / improved MIDP that comes in many varieties and is made for more powerful devices. For CDC there is the FP (Foundation Profile), which has more core classes from the Standard Edition of Java, the PBP (Personal Basis Profile) which extends the FP with more UI classes (from the Java 2 Standard Edition AWT Classes). Finally the PP (Personal Profile) adds to the PBP with more UI classes and applet support.
Optional packages provide even more functionality to your program by defining new sets of API’s that don’t really fit into any profile. Profiles may contain more specific API’s, but none of them are optional, i.e. if a device supports a profile, it must support everything defined within that profile. An API for Bluetooth, for example, would fit into the category of an optional package- simply because making it a part of a profile would limit that particular profile to only Bluetooth-enabled devices.
The most common Configuration for simple mobile phones is the CLDC, and the Profile MIDP, hence, this is what this article will cover.
HOW TO START:
Since this is a different type of Java Development, trying to build J2ME projects from your regular IDE might not work (unless it supports wireless development or you get a J2ME plug-in). The easiest way to build J2ME projects used to be with something called the Wireless Tool Kit, available for download from the Java site. You can now also just get the Java Platform Micro Edition Software Development Kit 3.0 [url=”http://java.sun.com/javame/downloads/sdk30.jsp”]J2ME SDK 3.0[/url]. If you have the old WTK program (before it was implemented into the SDK) get the 'ktoolbar.exe' program up and running, create a new project and the Toolkit will create all the necessary directories and files for you in it's apps directory, if you have the new J2ME SDK, simply run the main application, it's a fully featured IDE, so create a new project and you’re ready to go. When you create your project, you'll need to make sure you have the settings right- you need the correct MIDP and CLDC versions for your phone. You can set these by choosing the right target platform, and choosing the available options. If you create an application that’s ‘invalid’ when you try to run it on your device, then you are probably trying to use a version of CLDC or MIDP that your device doesn’t support. The J2ME SDK comes with many mobile phone emulators, simulating how your application will run under different phone model environments / constraints. Although this is nice and simple way to test your application, whilst your project / application is under development you should load it onto your device and test it under that environment often. Installing these applications on your phone can differ from model to model. Some phones you can simply drag and drop the .jar and the .jad files where you want them, some phones you can’t. You may want to see if you can get software from your device manufacturer, i.e. Nokia’s ‘Nokia PC Suite’. Some manufacturer software allows you to install your applications in different ‘environments’, this gives you application more or less freedom security-wise.
PORTABILITY
A very important issue with all developed applications is portability, and J2ME development is no different. Not only is there capability difference with this type of development (different MIDP / CLDC versions), there is also device-specific restrictions to take careful note of. These restrictions are things like screen size, amount of keypad buttons, types of buttons, graphical / audio capabilities etc. With these in mind, it is a lot easier to develop for a specific device model but this is not always an option. To create applications that are portable with a wider range of devices, you should be as general as possible . By this I mean that you reference specific details as little as possible. An example of this would be that if your mobile phone that you were creating an application for had a screen of about 200x200, and you wanted to draw (Low-Level UI) a proportioned rectangle of 20x20 (one tenth by one tenth), halfway from the top, and a quarter way from the left, rather than doing this:
CODE :
_____________________________________________________
//g is an object of Graphics
g.drawRect(50, 100, 20, 20); //x, y, width, height
_____________________________________________________
You should do something like this:
CODE :
____________________________________________________________________________
g.drawRect(this.getWidth()/4, this.getHeight()/2, this.getWidth ()/10, this.getHeight()/10);
____________________________________________________________________________
In this way, the scene would appear the same on different phone models of different screen sizes, because all the dimensions are adjusted to their environment. This same practice should be carried out as much as possible in all areas of your development. Another thing to consider is that the devices that you’re creating applications for are small / lightweight. I.e. they have little memory and for the most part a slower / lighter processor. For this reason, you must try to program in an efficient manner, so as to ensure your application works well with a range of different phone models. It’s very tempting to implement Runnable (use multithreading) for every class you have that extends Canvas, so you can keep up a constant repaint() (constantly update the screen). This coupled with other classes that rely upon multithreading can slow down your application or cause it to have a different performance on other phone models, so you should try to only use multithreading when it’s absolutely necessary.
PARTS OF A J2ME PROGRAM:
Just as you have Applications for the computer and Applets for the web, you have MIDlets for the wireless device. The entry point for your J2ME program must inherit (extend) MIDlet, but other classes you make don't have to. Like the Applet class, the MIDlet class is abstract, and so has required methods that any class inheriting MIDlet needs to override. These methods are:
CODE :
___________________________________________________________________________
public void startApp(){
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
___________________________________________________________________________
Putting this into perspective, a general MIDlet template would look like this (excluding user-interaction support / multithreading support / Any Display support, added in a nice, common, way to close application through exit()):
http://www.blogger.com/img/blank.gif
CODE :
_______________________________________________________________________
//File: MyMIDlet.java
import javax.microedition.midlet.*; //MIDlet
import javax.microedition.lcdui.*; //UI
public class MyMIDlet extends MIDlet
{
public MyMIDlet(){
}
public void startApp(){
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
private void exit() {
System.gc(); //Garbage Collect
destroyApp(false); //Run destroyApp method
notifyDestroyed(); //Let application know it’s now in destroyed //state
}
}
_______________________________________________________________________
All J2ME classes can be found in javax.microedition.*;
Classes that extend various other abstract J2ME classes (such as Canvas etc) will also have methods that will need to be overwritten.
Already you may notice a problem here- the main class needs to extend MIDlet, which means that it can’t inherit any other superclasses (although it can implement whatever it wants)- so what do we do when we want to draw to the screen and so on? The answer is simple, make different classes for the different ‘screens’ you wish your application to display at various times, have those classes extend the necessary superclass, and then to show them, simple transfer the display focus from the main MIDlet onto the class of the “screen” you wish to show. To transfer focus, the target must be a subclass of ‘Displayable’ (see Display Hierarchy in ADDITIONAL), i.e. a subclass of Screen, Canvas etc.
In the following example, the application enters at MyMIDlet, and then the MyMIDlet class transfers focus onto the MyCanvas class which fills the screen with white and draws a black string. In this way, the MyCanvas class is a ‘screen’, and you can quite easily make different classes to represent different ‘screens’ in your application and transfer focus between them whenever you wish. More on drawing and graphics will be covered in the DRAWING AND GRAPHICS section.
CODE :
__________________________________________________________________________
//File MyMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class MyMIDlet extends MIDlet
{
private Display display;
private MyCanvas canvas;
public MyMIDlet(){
display = Display.getDisplay(this);
canvas = new MyCanvas();
}
public void startApp(){
display.setCurrent(canvas);
}
public void pauseApp(){
}
public void destroyApp(boolean unconditional){
}
}
//File MyCanvas.java
import javax.microedition.lcdui.*;
public class MyCanvas extends Canvas
{
public MyCanvas(){
}
public void paint(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(0x000000);
g.drawString(“You’re in MyCanvas!”, 20, 20, Graphics.LEFT | Graphics.TOP);
}
}
__________________________________________________________________________
A finished j2me application consists of two files, a .jar and a .jad. The .jar file holds all the classes, resources and the manifest file, whereas the .jad is a descriptor, i.e. it ‘describes’ the j2me application to the device that will run it. If you are not using an IDE, you will need to package all the necessary files into a jar, and create an appropriate .jad file. (Although it is a lot easier to let the IDE take care of this for you). Here is what a typical .jad file looks like:
CODE :
__________________________________________________________________________
MIDlet-1:
MIDlet-Jar-Size:
MIDlet-Jar-URL:
MIDlet-Name:
MIDlet-Vendor:
MIDlet-Version:
MicroEdition-Configuration:
MicroEdition-Profile:
__________________________________________________________________________
To put this into perspective, here’s the current .jad file for my J2ME Sokoban game:
CODE :
__________________________________________________________________________
MIDlet-1: SokobanMain,/BOX1.png,SokobanMain
MIDlet-Jar-Size: 317218
MIDlet-Jar-URL: SOKOBANv2.jar
MIDlet-Name: SOKOBANv2
MIDlet-Vendor: ELJONTO
MIDlet-Version: 2.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-2.0
__________________________________________________________________________
Wrapping up parts of a J2ME application, you have the main entry class that inherits MIDlet and overrides all abstract methods, and then you have the other application classes who can transfer display focus between them if they are subclasses of Displayable.
DRAWING AND GRAPHICS
MIDlet’s have control over the screen through an object of Display. Each MIDlet can have only one Display object, and it is a superclass for Displayable. Display is used to represent the hardware for the display, whereas Displayable is used as a means of physically displaying something on the screen. Although there can be only one Display object for each MIDlet, there can be many objects of Displayable (because Displayable inherits Display, and all UI classes are beneath Displayable on the UI hierarchy, see Display Hierarchy in ADDITIONAL). This means, that every UI component, be it high level or low level inherits Displayable, and thus can be draw onto the device screen.
There exist two types of UI’s in J2ME, high level and low level. There are two direct subclasses of Displayable, Screen and Canvas. Screen is for high-level UI, and Canvas is for low-level UI. The difference between these is that Screen gives you access to pre-defined controls, such as text boxes, text fields- like the basic ones found in the Java SE awt packages. This gives you easy access to very powerful controls and UI components / elements which are very compatible with a large range of different devices. You can’t, however, draw directly to the screen. This is very limiting for most applications, especially games- where you need direct access to the screen to draw shapes etc. The ability to draw directly to the screen is done through the low-level UI classes of Canvas and Graphics. Canvas is an abstract class, where you need to overwrite the paint method. The paint method in your Canvas class is defined as follows:
CODE :
__________________________________________________________________________
public void paint(Graphics g){}
__________________________________________________________________________
This can be used in very much the same fashion as the paint method used in Java Applets, and through the Graphics object you can draw directly onto the screen of the device. There is also a subclass of Canvas called GameCanvas. This is like the regular Canvas class, but has been tweaked a bit for game development. It too, operates at a low level when it comes to drawing and graphics. The GameCanvas class will be discussed in a later article. The default origin (0,0) when drawing to the screen is at the top left of the device screen. Some drawing methods in Graphics take an integer alignment as a parameter (e.g drawString(), drawImage()). The options you have are:
Graphics.LEFT,
Graphics.RIGHT,
Graphics.TOP,
Graphics.BOTTOM,
Graphics.HCENTER,
Graphics.VCENTER,
Graphics.BASELINE.
These are OR’d together to give the alignment position of what you want to draw. I.e., to specify an image should be drawn in the middle of the screen, in the middle of the image:
CODE :
__________________________________________________________________________
//g is an object of Graphics
g.drawImage(image, this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
__________________________________________________________________________
If you’ve ever programmed a Java Applet before (Very unlikely that you haven’t if you’re reading this), then you’ll know that mixing the controls (text fields, text areas, buttons, etc) in the awt packages and drawing directly to the Applet from the paint method work together without any problems. In J2ME development, this is not the case. High-level UI and Low-level UI can’t mix, different ‘screens’ in your application can use different UI levels, but display must be transferred between them, it can’t be on both levels at the same time.
FILE HANDLING:
There are two types of data / file handling in J2ME, the first is like regular data / file handling on your computer, where you open a path, browse directories etc. This is done with the FileConnection API. A large part of Java development is security, therefore, having any application being able to read / write data / files natively on the device would be a huge security risk. This is where problems arise, unless your application is trusted, this type of file handling might request a response from the user every time it tries to read / write data to the file system, and some phone models might not allow it at all. These restrictions are unnecessary if all you want your program to do is save some options, game highs scores, unlocked levels etc. This brings us to the second type of file / data handling, persistent, through the RMS (Record Management Store) API. The RMS reads / writes data through a file / database crossover. Each MIDlet can have any number of RecordStores, and in MIDP version 2.0 MIDlet’s can access other MIDlet’s RecordStores (not discussed in this overview). All data inside the RecordStores are saved as Records, every Record is an array of bytes, and each record has an integer identifier. The RecordStores are protected from corruption by features like automatic synchronization etc, however it is still up to you to control access to the RecordStores in your application. This article will only detail using the RMS method of data / file handling because in most situations, the MIDlet needs to be signed to use the FileConnection API, or be installed in a trusted environment.
PROGRAM ACTION AND INTERACTION
Here I’ll explain how do to the various things in your J2ME application, such as drawing, handling events etc, and in SAMPLE PROGRAMS you can see these concepts as completed demo applications, with complete source code. I am not going to explain every member method for everything I describe here, some are self-explanatory, some you might need to look up, but this section is not a complete reference.
== Catching Keys:
Listening and catching keys (Not commands) in J2ME is done through the low-level UI classes of Canvas or GameCanvas, via the methods:
CODE :
__________________________________________________________________________
protected void keyPressed(int keyCode){}
protected void keyReleased(int keyCode){}
__________________________________________________________________________
Where keyCode is the code of the key that has been pressed / released. Key Catching in high-level UI is either handled automatically by the control, or done by catching the softkeys (More on softkeys in next subsection).
If you are creating your own low-level UI controls (e.g. a custom text field) that uses user input via the keypad, the keyCode for keys 0-9 will be the ASCII equivalents (48 - 57) so casting to char ((char)keyCode) will give you the number pressed. The other, non-keypad buttons have a negative keyCode, some of these values can be found here: http://www.j2meforums.com/wiki/index.php/Canvas_Keycodes .
If the Canvas that’s catching keys is being used for a game, using keyCode directly can be annoying, so instead we can use the method getGameAction(), and then choose from the list of statics in javax.microedition.lcdui.Canvas;
Example:
CODE :
__________________________________________________________________________
//Without using getGameAction()
protected void keyPressed(int keyCode){
if(keyCode == -1){
//Up Pressed
}else if(keyCode == -2){
//Down Pressed
}else if(keyCode == -3){
//Left Pressed
}else if(keyCode == -4){
//Right Pressed
}
}
//Using getGameAction()
protected void keyPressed(int keyCode){
int gameAction = getGameAction(keyCode);
if(gameAction == UP){
//Up Pressed
}else if(gameAction == DOWN){
//Down Pressed
}else if(gameAction == LEFT){
//Left Pressed
}else if(gameAction == RIGHT){
//Right Pressed
}
}
__________________________________________________________________________
The statics in javax.microedition.lcdui.Canvas that you can use are:
DOWN, FIRE, GAME_A, GAME_B, GAME_C, GAME_D, KEY_NUM0, KEY_NUM1, KEY_NUM2, KEY_NUM3, KEY_NUM4, KEY_NUM5, KEY_NUM6, KEY_NUM7, KEY_NUM8, KEY_NUM9, KEY_POUND, KEY_STAR, LEFT, RIGHT, UP
== Using CommandListener and Soft Keys
Soft Keys are the keys that aren’t part of the numpad, they’re usually situated above the numpad, but underneath the screen (on a typical mobile phone). They are keys such as the navigation joystick, the answer call / hang-up call/ select button etc. You may have noticed that it’s impossible in most case to get control of these for use in your application through the low-level UI key catching methods. There’s a reason for this, these are Command buttons. The other buttons, such as a 0 on the numpad, will always be and represent a 0 on the numpad (in this example). These Command buttons, however, can represent anything you want, from an Exit button, to a Select button, an Options button etc. Another reason is that these must be available to both high and low level UI implementations, and the keyPressed() and keyReleased() methods are a part of Canvas, low level UI.
To make use of these keys, you need to implement the interface CommandListener, and control the actions through:
CODE :
__________________________________________________________________________
public void commandAction(Command c, Displayable d){}
__________________________________________________________________________
Where “Command c” is the activated command and “Displayable d” is the Displayable object that activated the command. The class that implements CommandListener and hence has the method commandAction() can control the commands of any Displayable object as long the commandListener for the said object is set to the class implement CommandAction. This means that it is possible to have only one class implementing CommandListener, which controls all commands of all Displayable objects (Canvas, GameCanvas, Form, List etc).
To catch softkeys, you need to create a Command object for each command you want, add the Command objects to the displayable object you want the commands on, and set the commandListener of the displayable object to a CommandListener implementation that has the commandAction() method.
An example of usage, complete code will be in SAMPLE PROGRAMS section:
CODE :
__________________________________________________________________________
private MyCanvasClass mycanvas;
private Command exitCmd;
…
display = Display.getDisplay(this);
mycanvas = new MyCanvasClass();
exitCmd = new Command(“exit”, Command.EXIT, 0);
…
mycanvas.addCommand(exitCmd);
mycanvas.setCommandListener(this);
display.setCurrent(mycanvas);
…
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
__________________________________________________________________________
The Command constructor takes three parameters, the first being a label, String with the text the command will show. The second being a type, one of:
Command.BACK
Command.CANCEL
Command.EXIT
Command.HELP
Command.ITEM
Command.OK
Command.SCREEN
Command.STOP
The third parameter taken is an Integer priority. The Type and Priority parameters are how you can tell your device which commands should be assigned to what soft keys. For example on my current phone, the Nokia 6300, the command with the highest priority gets assigned to the center soft key, and commands of type Command.EXIT get assigned to the left soft key at the bottom of the screen. If there are more commands than soft keys available, a pop-up menu is automatically created on one of the soft keys, allowing the user to choose the other commands. Note that the command / soft key assignment is different on different devices.
== Predefined Controls and High Level UI Elements
Just like there exist UI controls for you to use in the java applet awt packages, there also exist similar controls in the J2ME lcdui packages. These UI controls are High level UI, because they are below the Screen class on the Display hierarchy (Display Hierarchy in ADDITIONAL), and cannot be mixed with low level UI access, as I mentioned earlier. Because these controls are High-level UI, you have very limited access when it comes to displaying them. This makes them very portable and a good option for creating an interface for the user to input data, but a bad option for game development, or any application where you’d like to have full control over the screen and appearances.
On the High-Level UI hierarchy directly underneath Screen are the classes Alert, List, TextBox and Form. All of these use the whole display. The ‘Ticker’ control, however, isn’t a control; it’s a variable in the Screen class.
-Alert
An Alert is essentially a very simple dialog box. It can have text, pictures and a sound warning. Alerts can either run until the user acknowledges it, or it can run for a pre-determined amount of time. When an alert finishes it will return focus to the last Displayable object that held focus (I.E. the Displayable object that ‘called’ it). However, if you want to transfer focus to a different displayable object when the alert finishes, add the other Displayable object as a parameter to setCurrent(); like so:
CODE :
__________________________________________________________________________
display.setCurrent(alert, newdisplayableobject);
__________________________________________________________________________
Creating a new Alert object:
CODE :
__________________________________________________________________________
Alert alert = new Alert("Alert Title Text", "Alert body text", alertImage, alertType);
__________________________________________________________________________
alertType is a static from the AlertType class, it is a sound for the alert and can be: AlertType.ALARM, AlertType.CONFIRMATION, AlertType.ERROR, AlertType.INFO, AlertType.WARNING.
The setTimeout method will set the amount of time in milliseconds that the alert will stay active.
CODE :
__________________________________________________________________________
alert.setTimeout(2000); //2 seconds
__________________________________________________________________________
If you want the alert to remain until the user acknowledges it, use the static FOREVER
CODE :
__________________________________________________________________________
alert.setTimeout(Alert.FOREVER);
__________________________________________________________________________
If an Alert is set to Alert.FOREVER and you don’t add any commands and don’t set a commandListener onto an Alert object, it will have a ‘done’ option by default, however if you do, you will need to define all commands.
-List
A list can present a series of choices, accompanied with images, for the user to choose (I.E. a menu). A List can be MULTIPLE / EXCLUSIVE, making it effectively a full-screen ChoiceGroup (discussed later), but benefits most as a menu if it is IMPLICIT.
Creating a list object:
CODE :
__________________________________________________________________________
List list = new List(“List Title”, List.IMPLICIT, listOptions, listImages);
__________________________________________________________________________
Where listOptions is a String array containing menu options and listImages is an Image array containing Images corresponding to the options.
If you don’t want to include any images, set the parameter to null.
To find out which option(s) are selected you can use:
CODE :
__________________________________________________________________________
list.getSelectedIndex();
__________________________________________________________________________
However, if you are using an IMPLICIT list, and have set a command listener onto it you can use this in your commandAction() method:
CODE :
__________________________________________________________________________
public void commandAction(Command c, Displayable d){
if(c == List.SELECT_COMMAND){
switch(list.getSelectedIndex()){
case n:
//etc
break;
default:
break;
}
}
}
__________________________________________________________________________
-TextBox
A TextBox is a multi-line control which allows users to enter text.
Create a TextBox object:
CODE :
__________________________________________________________________________
TextBox txtBox = new TextBox(“TextBox title”, “Text inside of textbox”, charlimit, restrictions);
__________________________________________________________________________
Where ‘charlimit’ is an integer which defines the max amount of characters that can be entered, and ‘restrictions’ is a static int from the TextField class, which defines the type of text that can be entered. The Options are: ANY, NUMERIC, PASSWORD, PHONENUMBER, EMAILADDR, and URL.
Use the OR operator to combine these:
CODE :
__________________________________________________________________________
TextField.EMAILADDR | TextField.PASSWORD
__________________________________________________________________________
This would only accept a valid email address and it would mask the input like a password field.
*Note: If you are having text inside of a TextBox, make sure it doesn’t exceed the charlimit you set; otherwise an IllegalArgumentException will be thrown.
-Ticker
A Ticker is a little banner of scrolling text (like HTML marquee, you know, the scrolling text that you see advertising stuff on crappy websites) at the top of a direct descendant of Screen (Alert, TextBox, List, and Form). Ticker is not a child of Screen; it is a variable, which is why it can be displayed on Screen children.
Create a new Ticker object:
CODE :
__________________________________________________________________________
Ticker tckr = new Ticker("A ticker, not a control- a variable of Screen");
__________________________________________________________________________
To add a Ticker object to a direct Screen child use the method:
CODE :
__________________________________________________________________________
screenchild.setTicker(tickerobject);
__________________________________________________________________________
-Form
A Form is a direct child of Screen that can hold all typical UI controls. These controls are of superclass Item (ChoiceGroup, CustomItem, DateField, Gauge, ImageItem, Spacer, StringItem, and TextField) see the Display Hierarchy in ADDITIONAL. Like the other direct children of Screen, Form uses the whole display, but unlike the others (except List) it will scroll to accommodate the Item’s it houses. A Form is arranged in “rows”, and it will try to put as many controls as it can onto each row. With small-screened devices, usually only one control fits per row. If your device can fit more than one control per row, to tidy up the layout you can use Spacers (discussed later) and the layout options in Item.
Create a form object:
CODE :
__________________________________________________________________________
Form frm = new Form(“Form Title”);
__________________________________________________________________________
Once you have created a form object, you add Item’s onto it using the append method
CODE :
__________________________________________________________________________
frm.append(item);
[code]
Every Item on a form can have a layout, set with the method:
[code]
setLayout(int layout);
__________________________________________________________________________
where layout can be:
Item.LAYOUT_2, Item.LAYOUT_BOTTOM, Item.LAYOUT_CENTER, Item.LAYOUT_DEFAULT, Item.LAYOUT_EXPAND, Item.LAYOUT_LEFT, Item.LAYOUT_NEWLINE_AFTER, Item.LAYOUT_NEWLINE_BEFORE, LAYOUT_RIGHT, Item.LAYOUT_SHRINK, Item.LAYOUT_TOP, Item.LAYOUT_VCENTER, Item.LAYOUT_VEXPAND, Item.LAYOUT_VSHRINK.
Since Form is Displayable, it too can have commands, command listeners etc
Following are descriptions of the controls that can appear on a form:
-ChoiceGroup
The ChoiceGroup control is like a list, it presents the user with a selection to choose from. There are two types of ChoiceGroup, multiple-selection (checkbox) and exclusive-selection (radio-group).
Create a ChoiceGroup object:
CODE :
__________________________________________________________________________
ChoiceGroup cg = new ChoiceGroup(“ChoiceGroup title”, type);
__________________________________________________________________________
Or create a ChoiceGroup object with options / images:
CODE :
__________________________________________________________________________
ChoiceGroup cg = new ChoiceGroup(“ChoiceGroup title”, type, options, images);
__________________________________________________________________________
Where type is either ChoiceGroup.MULTIPLE or ChoiceGroup.EXCLUSIVE, options is a String array containing the choices and images are the corresponding images to accompany the choices. Use null for the image parameter if you aren’t having any images.
To add an option to your ChoiceGroup object:
CODE :
__________________________________________________________________________
cg.append(“option”, image);
Where image is the accompanying image, otherwise use null.
To get the selected options you can use:
CODE :
getSelectedIndex();
__________________________________________________________________________
Or to return a boolean array of the selected / unselected:
CODE :
__________________________________________________________________________
getSelectedFlags(returnArray);
__________________________________________________________________________
Where returnArray is a boolean array.
-CustomItem
A CustomItem lets you define your own Item to place on a form. To create a new CustomItem, create a class for your control, have it extend CustomItem. The CustomItem constructor requires a String title, and since it’s abstract you need to use a few methods. This leaves the shell of a CustomItem subclass looking like:
CODE :
__________________________________________________________________________
class MyItem extends CustomItem
{
public MyItem(String title){
super(title);
}
protected int getMinContentHeight() {}
protected int getMinContentWidth() {}
protected int getPrefContentHeight(int width) {}
protected int getPrefContentWidth(int height) {}
protected void paint(Graphics g, int w, int h) {}
}
__________________________________________________________________________
If we were to finish our MyItem (This will be covered in a later article), using it would be the same as the other Items:
CODE :
__________________________________________________________________________
MyItem myItem = new MyItem(“My Custom Item”);
form.append(myItem);
__________________________________________________________________________
-DateField
A DateField Item lets you view / change the date and time.
Creating a DateField object:
CODE :
__________________________________________________________________________
DateField df = new DateField(“Title”, type);
DateField df = new DateField(“Title”, type, timezone);
__________________________________________________________________________
Where type is either DateField.DATE, DateField.TIME, DateField.DATE_TIME, allowing the user to edit the date, the time, or both (respectively). The timezone parameter is an object of TimeZone.
You can set / get the date using:
CODE :
__________________________________________________________________________
df.setDate(date);
Date date = df.getDate();
__________________________________________________________________________
Where Date is defined in the java.util package.
-Gauge
A gauge is meter that displays the progress of something. It’s typically used to show the volume level when adjusting, however if can be used for whatever you want. You can have an interactive gauge (I.E. volume control), or a non-interactive gauge where the application itself must change the value.
Creating a gauge object:
CODE :
__________________________________________________________________________
Gauge gauge = new Gauge(“Title”, interactive, maxvalue, startvalue);
__________________________________________________________________________
Where interactive is a boolean, true: interactive, false: non interactive, maxvalue is an integer for the maximum value of the gauge and startvalue is the value the gauge should start at.
To get / set the value of a Gauge object:
CODE :
__________________________________________________________________________
gauge.setValue(integervalue);
int value = gauge.getValue();
__________________________________________________________________________
-ImageItem
An ImageItem lets you put an image onto a form.
Create and ImageItem object:
CODE :
__________________________________________________________________________
ImageItem imageItem = new ImageItem(“Title”, image, layout, “Alt text”);
__________________________________________________________________________
Where image is an object of type Image, layout is any of the LAYOUT statics in Item (mentioned above in –Form section).
You can create an Image Object using Image.createImage(). This method is overridden quite a few times, but the easiest way takes only a String path to an image file:
CODE :
__________________________________________________________________________
Image.createImage(String imagePath);
__________________________________________________________________________
-Spacer
A Spacer is simply a section of white space that you can size accordingly and use to put some extra ‘space’ into your form to help with layout.
Create a Spacer object:
CODE :
__________________________________________________________________________
Spacer spcr = new Spacer(horizPadding, vertPadding);
__________________________________________________________________________
Where horizPadding is an integer value for the horizontal white space and vertPadding is an integer value for the vertical white space.
Simply append the Spacer object to the form wherever you want the white space.
-StringItem
A StringItem is simply a label control to put text onto a form.
Create a StringItem object:
CODE :
__________________________________________________________________________
StringItem str = new StringItem(“Title”, “Your Text”);
__________________________________________________________________________
Alternatively, you can add text onto a form by simply appending a String:
CODE :
__________________________________________________________________________
form.append(“Text to put on form”);
__________________________________________________________________________
The reason there exists a StringItem class when you can use the above method is so that you can get / set the text etc.
CODE :
__________________________________________________________________________
String recvStr = str.getText();
Str.setText(“New Text”);
__________________________________________________________________________
-TextField
A TextField is a single-line TextBox control, which allows the user to enter the type of text allowed. TextBox shares the same text restrictions as TextField, which are: TextField.ANY, TextField.NUMERIC, TextField.PASSWORD, TextField.PHONENUMBER, TextField.EMAILADDR, and TextField.URL. Look up the TextBox section for more on using these restrictions.
Create a TextField object:
CODE :
__________________________________________________________________________
TextField txt = new TextField(“Title”, “Text in box”, charlimit, restrictions);
__________________________________________________________________________
Where charlimit is an integer to represent the max allowed characters (make sure if you have text inside the text field on initialisation that it doesn’t exceed the limit) and restrictions is an integer for a static restriction from the TextField class (discussed above).
== Using ItemStateListener
Where CommandListener is triggered on interaction with commands, ItemStateListener is triggered on interaction with controls. Using ItemStateListener is very similar to using CommandListener (discussed earlier). The class that’s going to listen for state changes will need to implement ItemStateListener, and then override the method:
CODE :
__________________________________________________________________________
public void itemStateChanged(Item i){}
__________________________________________________________________________
To set up a Displayable object to listen for state changes, use the method:
CODE :
__________________________________________________________________________
displayableObj.setItemStateListener(listener);
__________________________________________________________________________
where listener is the class that implements ItemStateListener, and hence has the itemStateChanged() method.
An example of usage is shown in SAMPLE PROGRAMS.
== Multithreading
There’s nothing special to multithreading in J2ME development, it can be used by inheriting Thread or implementing Runnable. J2ME classes that serve a UI purpose usually inherit a class (Canvas, GameCanvas etc) so it’s generally easier to use the implementation method. Multithreading should be used as little as possible in this type of development, bearing in mind the type of processor the destined device has. Obviously there are some situations where it’s absolutely necessary, such as updating a game screen, but it’s important to not go overboard. To limit multithreading in your J2ME application, you may need to reorganise your code a bit, so that you end up having one class with multithreaded support, updating the activities of the other classes that would have normally been multithreaded. In many situations this might not be preferable, but just try to use it as little as possible.
== RMS File Handling
See FILE HANDLING for an explanation of RMS.
The import:
CODE :
__________________________________________________________________________
import javax.microedition.rms.*;
Create / Open a RecordStore:
CODE :
__________________________________________________________________________
RecordStore recStore = RecordStore.openRecordStore(name, createIfDoesntExist);
__________________________________________________________________________
Where name is the String name of the RecordStore and createIfDoesntExist is a boolean variable, true to create the RecordStore if it doesn’t exist, if it does exist, the RecordStore will be opened. False to not create the RecordStore if it doesn’t exist, if it does exist, the RecordStore will be opened.
Delete a RecordStore:
CODE :
__________________________________________________________________________
RecordStore.deleteRecordStore(name);
__________________________________________________________________________
Where name is the String name of the RecordStore to delete.
Close a RecordStore:
CODE :
__________________________________________________________________________
recStore.closeRecordStore();
__________________________________________________________________________
Add a Record:
CODE :
__________________________________________________________________________
recStore.addRecord(data, offset, bytesAmount);
__________________________________________________________________________
Where data is a byte array, offset is where you want to start writing to in the Record and bytesAmount is the number of bytes from data you want written. The addRecord() method returns the ID of the record you added.
Set / Overwrite a Record:
CODE :
__________________________________________________________________________
recStore.setRecord(recID, data, offset, bytesAmount);
__________________________________________________________________________
Same as the addRecord() method, only you need to include the recID parameter, which is the integer ID of the Record you want to overwrite.
Delete a Record:
CODE :
__________________________________________________________________________
recStore.deleteRecord(recID);
__________________________________________________________________________
Where recID is the integer ID of the Record you want to delete.
Get a Record:
CODE :
__________________________________________________________________________
byte[] data = recStore.getRecord(recID);
//OR
recStore.getRecord(recID, data, offset);
__________________________________________________________________________
Where recID is the Integer ID of the Record you want, data is a byte[] array to hold the bytes and offset is an Integer offset to say where to start reading from.
SAMPLE PROGRAMS:
Here are three, ready-to-compile and run J2ME applications, that use most of what is described or presented in this article. The first will display the High-Level UI, some controls, and using the Listeners, the second- the Low Level UI with Multithreading and the last, the RMS file handling / database emulating system. When I say ‘application’, I am not referring to something built to solve a problem, hell, or even be useful- these are just a compilation of some of the things shown here so you can see them work, and to give you an idea of how to implement them.
== High Level UI, CommandListener, ItemStateListener
CODE :
__________________________________________________________________________
//File: DemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class DemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private ListDemo listDemo;
private TextBoxDemo textBoxDemo;
private FormDemo formDemo;
private AlertDemo alertDemo;
private Command exitCmd, menuCmd;
public DemoMIDlet(){
display = Display.getDisplay(this);
listDemo = new ListDemo("A List Menu", List.IMPLICIT, new String[]{"TextBox", "Form", "Alert"}, null);
textBoxDemo = new TextBoxDemo("A TextBox", "Stuff inside textBox, 500 char limit, ANY text", 500, TextField.ANY);
formDemo = new FormDemo("A Form");
alertDemo = new AlertDemo("An INFO Alert", "Alert content", null, AlertType.INFO);
exitCmd = new Command("Exit", Command.EXIT, 0);
menuCmd = new Command("Menu", Command.BACK, 1);
}
public void startApp() {
listDemo.addCommand(exitCmd);
listDemo.setCommandListener(this);
textBoxDemo.addCommand(exitCmd);
textBoxDemo.addCommand(menuCmd);
textBoxDemo.setCommandListener(this);
formDemo.addCommand(exitCmd);
formDemo.addCommand(menuCmd);
formDemo.setCommandListener(this);
display.setCurrent(listDemo);
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
private void exit() {
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}else if(c == menuCmd){
display.setCurrent(listDemo);
}else if(c == List.SELECT_COMMAND && d == listDemo){
switch(listDemo.getSelectedIndex()){
case 0:
display.setCurrent(textBoxDemo);
break;
case 1:
display.setCurrent(formDemo);
break;
case 2:
display.setCurrent(alertDemo);
break;
default:
break;
}
}
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: ListDemo.java
import javax.microedition.lcdui.*;
public class ListDemo extends List
{
public ListDemo(String title, int TYPE, String[] options, Image[] images){
super(title, TYPE, options, images);
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: TextBoxDemo.java
import javax.microedition.lcdui.*;
public class TextBoxDemo extends TextBox
{
public TextBoxDemo(String title, String content, int MAXSIZE, int TYPE){
super(title, content, MAXSIZE, TYPE);
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: FormDemo.java
/*
* Make sure you comment out the ImageItem parts if you don’t supply an image
*/
import java.io.IOException;
import javax.microedition.lcdui.*;
public class FormDemo extends Form implements ItemStateListener
{
private Ticker tckr;
private DateField df;
private StringItem str;
private Gauge gauge;
private Spacer spcr;
private TextField txt;
private ChoiceGroup cg;
private ImageItem imgItem;
public FormDemo(String title){
super(title);
tckr = new Ticker("A ticker, not a control- part of Screen");
df = new DateField("A Date Field control", DateField.DATE_TIME);
str = new StringItem("stritem", "TEXT");
gauge = new Gauge("Volume Gauge", true, 10, 6);
try{
imgItem = new ImageItem("An Image", Image.createImage("/image.png"), ImageItem.LAYOUT_DEFAULT, "Alternate text");
}catch(IOException e){}
spcr = new Spacer(0,40);
txt = new TextField("TextField", "Enter Text", 20, TextField.ANY);
cg = new ChoiceGroup("ChoiceGroup", ChoiceGroup.MULTIPLE);
cg.append("Choice 1", null);
cg.append("Choice 2", null);
this.setTicker(tckr);
this.append(df);
this.append(str);
this.append("String Message 2!");
this.append(spcr);
this.append(gauge);
this.append(txt);
this.append(cg);
this.append(imgItem);
this.setItemStateListener(this);
}
public void itemStateChanged(Item i){
str.setText(i.getLabel()+" has changed");
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: AlertDemo.java
import javax.microedition.lcdui.*;
public class AlertDemo extends Alert
{
public AlertDemo(String title, String content, Image image, AlertType TYPE){
super(title, content, image, TYPE);
}
}
== Canvas / Multithreading
CODE :
//File: DemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class DemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private CanvasDemo canvas;
private Command exitCmd;
public DemoMIDlet(){
display = Display.getDisplay(this);
canvas = new CanvasDemo();
exitCmd = new Command("Exit", Command.EXIT, 0);
}
public void startApp() {
canvas.addCommand(exitCmd);
canvas.setCommandListener(this);
display.setCurrent(canvas);
}
public void pauseApp() { }
public void destroyApp(boolean unconditional) {
}
private void exit() {
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
}
__________________________________________________________________________
CODE :
__________________________________________________________________________
//File: CanvasDemo.java
import java.io.IOException;
import javax.microedition.lcdui.*;
public class CanvasDemo extends Canvas implements Runnable{
private Thread MainThread;
private long sleep = 50;
private boolean run = true;
private String keyAction = "Key";
private Image img;
private int[] moveShapeLoc = {
this.getWidth()/10,
this.getWidth()/4,
this.getHeight()/8
};
private int[] autoShapeDim = {
this.getWidth()/2,
this.getHeight()/2,
this.getWidth()/10,
this.getHeight()/10,
};
private int direction;
private static int DIRECTIONLEFT = 0;
private static int DIRECTIONRIGHT = 1;
public CanvasDemo(){
MainThread = new Thread(this);
try{
img = Image.createImage("/image.png");
}catch(IOException e){}
direction = DIRECTIONRIGHT;
MainThread.start();
}
public void run(){
while(run){
autoShape();
repaint();
try{
Thread.sleep(sleep);
}catch(InterruptedException e){}
}
}
protected void keyPressed(int keyCode){
int gameAction = getGameAction(keyCode);
keyAction = "Key Down: (int)"+keyCode;
if(gameAction == LEFT){
moveShape(-4, 0);
}else if(gameAction == RIGHT){
moveShape(4, 0);
}else if(gameAction == UP){
moveShape(0, -4);
}else if(gameAction == DOWN){
moveShape(0, 4);
}
}
protected void keyReleased(int keyCode){
int gameAction = getGameAction(keyCode);
keyAction = "Key Up: (int)"+keyCode;
}
private void moveShape(int hspeed, int vspeed){
moveShapeLoc[1] += hspeed;
moveShapeLoc[2] += vspeed;
}
private void autoShape(){
if(direction == DIRECTIONLEFT){
if(autoShapeDim[0] > 0){
autoShapeDim[0]--;
}else{
direction++;
}
}else{
if(autoShapeDim[0] + autoShapeDim[2] < this.getWidth()){
autoShapeDim[0]++;
}else{
direction--;
}
}
}
public void paint(Graphics g){
g.setColor(0xFFFFFF);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(0x000000);
g.drawString("CanvasDemo", 1, 1, Graphics.LEFT | Graphics.TOP);
g.drawString(keyAction, 1, 20, Graphics.LEFT | Graphics.TOP);
g.fillRect(autoShapeDim[0], autoShapeDim[1],autoShapeDim[2],autoShapeDim[3]);
g.setColor(0xFF0000);
g.drawArc(moveShapeLoc[1], moveShapeLoc[2], moveShapeLoc[0]*2, moveShapeLoc[0]*2, 0, 360);
g.drawImage(img, this.getWidth()/2, this.getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
}
}
== RMS
CODE :
__________________________________________________________________________
//File: RMSDemoMIDlet.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.rms.*;
public class RMSDemoMIDlet extends MIDlet implements CommandListener{
private Display display;
private Form form;
private StringItem progress;
private Command exitCmd;
public RMSDemoMIDlet(){
display = Display.getDisplay(this);
form = new Form("RMS Demo");
progress = new StringItem("Progress:", "");
exitCmd = new Command("Exit", Command.EXIT, 0);
}
public void startApp() {
form.append(progress);
form.addCommand(exitCmd);
form.setCommandListener(this);
rmsDemo();
display.setCurrent(form);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
private void exit(){
System.gc();
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable d){
if(c == exitCmd){
exit();
}
}
private void rmsDemo(){
progress.setText(progress.getText() + "\n>>Attempting to create RecordStore 'RecStore'");
RecordStore rs = null;
try{
rs = RecordStore.openRecordStore("RecStore", true);
progress.setText(progress.getText() + "\n>>Created RecordStore");
progress.setText(progress.getText() + "\n>>Attempting to add records");
String[] records = {
"The first record",
"The second record",
"The third record",
"The fourth record",
};
for(int i = 0; i < records.length; i++){
rs.addRecord(records[i].getBytes(), 0, records[i].length());
}
progress.setText(progress.getText() + "\n>>Added records");
progress.setText(progress.getText() + "\n>>Attempting to read records: ");
for(int i = 1; i <= rs.getNumRecords(); i++){
progress.setText(progress.getText() + "\n");
for(int j = 0; j < rs.getRecord(i).length; j++){
progress.setText(progress.getText() + (char)(rs.getRecord(i)[j]));
}
}
progress.setText(progress.getText() + "\n");
progress.setText(progress.getText() + "\n>>Attempting to edit records");
for(int i = 1; i <= rs.getNumRecords(); i++){
String newData = records[i-1]+" edited";
rs.setRecord(i, newData.getBytes(), 0, newData.length());
}
progress.setText(progress.getText() + "\n>>Attempting to read new records: ");
for(int i = 1; i <= rs.getNumRecords(); i++){
progress.setText(progress.getText() + "\n");
for(int j = 0; j < rs.getRecord(i).length; j++){
progress.setText(progress.getText() + (char)(rs.getRecord(i)[j]));
}
}
progress.setText(progress.getText() + "\n");
progress.setText(progress.getText() + "\n>>Attempting to delete records");
for(int i = 1; i <= rs.getNumRecords(); i++){
rs.deleteRecord(i);
}
progress.setText(progress.getText() + "\n>>Deleted records");
progress.setText(progress.getText() + "\n>>Attempting to close RecordStore 'RecStore'");
rs.closeRecordStore();
progress.setText(progress.getText() + "\n>>RecordStore closed");
progress.setText(progress.getText() + "\n>>Attempting to delete RecordStore 'RecStore'");
RecordStore.deleteRecordStore("RecStore");
progress.setText(progress.getText() + "\n>>RecordStore deleted");
}catch(RecordStoreException e){
progress.setText(progress.getText() + "\n>>Fail: "+e.getMessage());
}
}
}
__________________________________________________________________________
ADDITIONAL
==Display Hierarchy:
Display
|
Displayable
| |
| Canvas
|
Screen
|
Form, List, Alert, TextBox
|
Item
|
ChoiceGroup, CustomItem, DateField, Gauge, ImageItem, Spacer, StringItem, TextField
OUTRO:
Well, that concludes my basic overview on coding with J2ME with the focus on mobile phone application development. I hope that you have found this useful, and all feedback (comments / suggestions / corrections) is very welcome. Feel free to contact me (eljonto {AT} live {DOT} com) if you have any questions, I’ll do my best to answer them. If I get around to writing more articles on J2ME, it will cover more areas, and revisit areas in depth (Such as Canvas, GameCanvas, etc), as this overview isn’t very comprehensive in many areas, if it was- it wouldn’t be a basic overview.
source : http://www.hackthissite.org/
Subscribe to:
Posts (Atom)