reorg of project assets

This commit is contained in:
Brian LeRoux 2010-01-26 13:54:02 -08:00
parent fc6f2f5d39
commit e3dc010b97
33 changed files with 360 additions and 377 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@ default.properties
bin
gen
assets/www/phonegap.js
local.properties
local.properties
framework/phonegap.jar

View File

@ -7,7 +7,7 @@ Pre-requisites
* Java JDK 1.5
* Android SDK Package [http://developer.android.com](http://developer.android.com)
* Apache ANT (For build script)
* Ruby, Rubygems, nokogiri (for build.rb)
* Ruby
Recommended:
----------------------------------------------------------------

View File

@ -1,80 +0,0 @@
require 'rubygems'
require 'nokogiri'
require 'fileutils'
class Build
attr_reader :path
attr_reader :name
attr_reader :package_name
attr_reader :www_dir
def start(name, pkg_name, www, path)
create_android(name, pkg_name, path)
@www_dir = www
generate_manifest
copy_libs
write_java
end
def create_android(name, pkg_name, path)
@name = name
@pkg_name = pkg_name
@path = path
`android create project -t 5 -k #{pkg_name} -a #{name} -n #{name} -p #{path}`
end
def generate_manifest
f = File.open('framework/AndroidManifest.xml', 'r')
doc = Nokogiri::XML(f.read)
manifest = doc.search('//manifest')
manifest[0]['package'] = @pkg_name
actions = doc.search('//activity')
actions[0]['android:name'] = ".#{@name}"
actions[1]['android:name'] = "com.phonegap.CameraPreview"
f = File.open("#{@path}/AndroidManifest.xml", 'w')
f.write(doc.to_xml)
end
def copy_libs
FileUtils.cp('framework/phonegap.jar', "#{@path}/libs")
FileUtils.cp('framework/res/values/strings.xml', "#{@path}/res/values/strings.xml")
FileUtils.mkdir_p("#{@path}/res/drawable/")
FileUtils.mkdir_p("#{@path}/assets")
FileUtils.cp_r("#{@www_dir}/", "#{@path}/assets/www")
FileUtils.cp("#{@www_dir}/icon.png", "#{@path}/res/drawable/icon.png")
end
def write_java
package_path = "#{@path}/src/" + @pkg_name.gsub('.', '/')
doc = File.open("#{package_path}/#{@name}.java", 'r')
data = doc.read.split(/\n/)
result = ""
data.each do |line|
if line.include? "android.os.Bundle"
line += "\n\nimport com.phonegap.*;"
end
if line.include? "extends Activity"
line = "public class #{@name} extends DroidGap"
end
if line.include? "setContentView"
line = " super.loadUrl(\"file:///android_asset/www/index.html\");"
end
result += line + "\n"
end
doc.close
package_path = "#{@path}/src/" + @pkg_name.gsub('.', '/')
target = File.open(package_path + "/#{@name}.java", 'w')
target.write(result);
end
end
b = Build.new
if(ARGV.length >= 3)
b.start(ARGV[0], ARGV[1], ARGV[2], ARGV[3])
else
str = "Android PhoneGap Build Tool \n Usage: build <name> <package_name> <wwwdir> <path> \n name: The name of your application \n package_name: The name of your package: i.e. com.nitobi.demo \n wwwdir: The name of your Web App \n path: Location of where you want to work on your application"
puts str
end

101
droidgap Executable file
View File

@ -0,0 +1,101 @@
#!/usr/bin/env ruby
class Build
def start(*args)
@android_sdk_path, @name, @pkg, @www, @path = args
build_jar
create_android
generate_manifest
copy_libs
write_java
end
# creates framework/phonegap.jar using android_sdk_path
#
# TODO
# - write out local.properties with android sdk every time
def build_jar
`touch #{ @android_sdk_path }` unless File.exists? @android_sdk_path
`ant jar`
end
# runs android create project
def create_android
`android create project -t 5 -k #{ @pkg } -a #{ @name } -n #{ @name } -p #{ @path }`
end
# creates an AndroidManifest.xml for the project
def generate_manifest
manifest = ""
open('framework/AndroidManifest.xml', 'r') do |old|
manifest = old.read
manifest.gsub! 'package="com.phonegap"', "package=\"#{ @pkg }\""
manifest.gsub! 'android:name=".StandAlone"', ".#{ @name }"
end
open("#{ @path }/AndroidManifest.xml", 'w') {|x| x.puts manifest }
end
# copies stuff from framework into the project
#
# TODO need to allow for www import
# - copy www into #{ @path }/assets/www
# - copy www/icon.png into #{ @path }/res/drawable/icon.png
#
def copy_libs
`cp framework/phonegap.jar #{ @path }/libs`
`cp framework/res/values/strings.xml #{ @path }/res/values/strings.xml`
`cp framework/res #{ @path }/res`
`cp framework/assets/www #{ @path }/assets/wwww`
end
# this is so fucking unholy yet oddly beautiful
# not sure if I should thank Ruby or apologize for this abusive use of string interpolation
def write_java
j = "
package #{ @pkg };
import android.app.Activity;
import android.os.Bundle;
import com.phonegap.*;
public class #{ @name } extends DroidGap
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.loadUrl(\"file:///android_asset/www/index.html\");
}
}
"
open("#{ @path }/src/#{ @pkg.gsub '.', '/' }",'w') { |f| f.puts j }
end
#
end
if(ARGV.length == 5)
Build.new.start(ARGV)
else
puts <<-EOF
DroidGap: An Android PhoneGap Project Generator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a fresh Android/PhoneGap app for hybrid mobile web hacking.
Usage:
./droidgap <android_sdk_path> <name> <package_name> <www> <path>
Params:
android_sdk_path ... The path to your Android SDK install.
name ............... The name of your application.
package_name ....... The name of your package (For example: com.nitobi.demo)
www ................ The name of your Web App.
path ............... Location of where you want to work on your application.
EOF
end

View File

@ -32,7 +32,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CameraPreview"
<activity android:name="com.phonegap.CameraPreview"
android:label="@string/app_name" android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden">
<action android:name="android.intent.action.PICK" />

View File

@ -1,6 +0,0 @@
Note: phonegap.js goes in the assets/www directory. To get this file, please
build it from the top level by running make:
make
The file will be concatenated and minified, and will be stored in lib/android

View File

@ -1,5 +1,4 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />

View File

@ -17,7 +17,7 @@ PhoneGap = {
/**
* Boolean flag indicating if the PhoneGap API is available and initialized.
*/
*/ // TODO: Remove this, it is unused here ... -jm
PhoneGap.available = DeviceInfo.uuid != undefined;
/**
@ -27,28 +27,51 @@ PhoneGap.available = DeviceInfo.uuid != undefined;
*/
PhoneGap.addConstructor = function(func) {
var state = document.readyState;
if (state != 'loaded' && state != 'complete')
PhoneGap._constructors.push(func);
if ( state == 'loaded' || state == 'complete' )
{
func();
}
else
func();
{
PhoneGap._constructors.push(func);
}
};
(function() {
var timer = setInterval(function() {
var state = document.readyState;
if (state != 'loaded' && state != 'complete')
return;
clearInterval(timer);
while (PhoneGap._constructors.length > 0) {
var constructor = PhoneGap._constructors.shift();
try {
constructor();
} catch(e) {
if (typeof(debug['log']) == 'function')
debug.log("Failed to run constructor: " + debug.processMessage(e));
else
alert("Failed to run constructor: " + e.message);
(function()
{
var timer = setInterval(function()
{
var state = document.readyState;
if ( state == 'loaded' || state == 'complete' )
{
clearInterval(timer); // stop looking
// run our constructors list
while (PhoneGap._constructors.length > 0)
{
var constructor = PhoneGap._constructors.shift();
try
{
constructor();
}
catch(e)
{
if (typeof(debug['log']) == 'function')
{
debug.log("Failed to run constructor: " + debug.processMessage(e));
}
else
{
alert("Failed to run constructor: " + e.message);
}
}
}
}
// all constructors run, now fire the deviceready event
var e = document.createEvent('Events');
e.initEvent('deviceready');
document.dispatchEvent(e);
}
}, 1);
})();
@ -65,14 +88,51 @@ PhoneGap.exec = function() {
if (PhoneGap.queue.timer == null)
PhoneGap.queue.timer = setInterval(PhoneGap.run_command, 10);
};
/**
* Internal function used to dispatch the request to PhoneGap. This needs to be implemented per-platform to
* ensure that methods are called on the phone in a way appropriate for that device.
* Internal function used to dispatch the request to PhoneGap. It processes the
* command queue and executes the next command on the list. If one of the
* arguments is a JavaScript object, it will be passed on the QueryString of the
* url, which will be turned into a dictionary on the other end.
* @private
*/
PhoneGap.run_command = function() {
};
if (!PhoneGap.available || !PhoneGap.queue.ready)
return;
PhoneGap.queue.ready = false;
var args = PhoneGap.queue.commands.shift();
if (PhoneGap.queue.commands.length == 0) {
clearInterval(PhoneGap.queue.timer);
PhoneGap.queue.timer = null;
}
var uri = [];
var dict = null;
for (var i = 1; i < args.length; i++) {
var arg = args[i];
if (arg == undefined || arg == null)
arg = '';
if (typeof(arg) == 'object')
dict = arg;
else
uri.push(encodeURIComponent(arg));
}
var url = "gap://" + args[0] + "/" + uri.join("/");
if (dict != null) {
var query_args = [];
for (var name in dict) {
if (typeof(name) != 'string')
continue;
query_args.push(encodeURIComponent(name) + "=" + encodeURIComponent(dict[name]));
}
if (query_args.length > 0)
url += "?" + query_args.join("&");
}
document.location = url;
};
function Acceleration(x, y, z)
{
this.x = x;
@ -294,58 +354,76 @@ Compass.prototype.setError = function(message) {
PhoneGap.addConstructor(function() {
if (typeof navigator.compass == "undefined") navigator.compass = new Compass();
});
/**
* This class provides access to the device contacts.
* @constructor
*/
function Contact(jsonObject) {
this.firstName = "";
this.lastName = "";
this.name = "";
this.phones = {};
this.emails = {};
this.address = "";
var Contact = function(){
this.name = null;
this.emails = [];
this.phones = [];
}
Contact.prototype.displayName = function()
var ContactName = function()
{
// TODO: can be tuned according to prefs
return this.name;
this.formatted = "";
this.familyName = "";
this.givenName = "";
this.additionalNames = [];
this.prefixes = [];
this.suffixes = [];
}
function ContactManager() {
// Dummy object to hold array of contacts
this.contacts = [];
this.timestamp = new Date().getTime();
var ContactEmail = function()
{
this.types = [];
this.address = "";
}
ContactManager.prototype.getAllContacts = function(successCallback, errorCallback, options) {
// Interface
var ContactPhoneNumber = function()
{
this.types = [];
this.number = "";
}
var Contacts = function()
{
this.records = [];
}
Contacts.prototype.find = function(obj, win, fail)
{
if(obj.name != null)
{
ContactHook.search(name, "", "");
}
this.win = win;
this.fail = fail;
}
Contacts.prototype.droidFoundContact = function(name, npa, email)
{
var contact = new Contact();
contact.name = new ContactName();
contact.name.formatted = name;
contact.name.givenName = name;
var mail = new ContactEmail();
mail.types.push("home");
mail.address = email;
contact.emails.push(mail);
phone = new ContactPhoneNumber();
phone.types.push("home");
phone.number = npa;
contact.phones.push(phone);
this.records.push(contact);
}
Contacts.prototype.droidDone = function()
{
this.win(this.records);
}
PhoneGap.addConstructor(function() {
if (typeof navigator.ContactManager == "undefined") navigator.ContactManager = new ContactManager();
if(typeof navigator.contacts == "undefined") navigator.contacts = new Contacts();
});
ContactManager.prototype.getAllContacts = function(successCallback, errorCallback, options) {
this.win = successCallback;
this.fail = errorCallback;
ContactHook.getContactsAndSendBack();
}
ContactManager.prototype.droidAddContact = function(name, phone, email)
{
var contact = new Contact();
contact.name = name;
contact.phones.primary = phone;
contact.emails.primary = email;
this.contacts.push(contact);
}
ContactManager.prototype.droidDone = function()
{
win(this.contacts);
}
/**
* this represents the mobile device, and provides properties for inspecting the model, version, UUID of the
* phone, etc.
@ -366,13 +444,7 @@ function Device() {
this.gapVersion = window.DroidGap.getVersion();
this.platform = window.DroidGap.getPlatform();
this.name = window.DroidGap.getProductName();
} else {
this.platform = DeviceInfo.platform;
this.version = DeviceInfo.version;
this.name = DeviceInfo.name;
this.gap = DeviceInfo.gap;
this.uuid = DeviceInfo.uuid;
}
}
} catch(e) {
this.available = false;
}
@ -380,9 +452,6 @@ function Device() {
PhoneGap.addConstructor(function() {
navigator.device = window.device = new Device();
var event = document.createEvent("Events");
event.initEvent('deviceReady', false, false);
document.dispatchEvent(event);
});
/**
* This class provides generic read and write access to the mobile device file system.
@ -680,6 +749,28 @@ Geolocation.prototype.clearWatch = function(watchId)
{
Geo.stop(watchId);
}
function KeyEvent()
{
}
KeyEvent.prototype.menuTrigger = function()
{
var e = document.createEvent('Events');
e.initEvent('menuKeyDown');
document.dispatchEvent(e);
}
KeyEvent.prototype.searchTrigger= function()
{
var e = document.createEvent('Events');
e.initEvent('searchKeyDown');
document.dispatchEvent(e);
}
if (document.keyEvent == null || typeof document.keyEvent == 'undefined')
{
window.keyEvent = document.keyEvent = new KeyEvent();
}
/**
* This class provides access to the device media, interfaces to both sound and video
* @constructor
@ -951,3 +1042,92 @@ PositionError.UNKNOWN_ERROR = 0;
PositionError.PERMISSION_DENIED = 1;
PositionError.POSITION_UNAVAILABLE = 2;
PositionError.TIMEOUT = 3;
/*
* This is purely for the Android 1.5/1.6 HTML 5 Storage
* I was hoping that Android 2.0 would deprecate this, but given the fact that
* most manufacturers ship with Android 1.5 and do not do OTA Updates, this is required
*/
var DroidDB = function()
{
this.txQueue = [];
}
DroidDB.prototype.addResult = function(rawdata, tx_id)
{
eval("var data = " + rawdata);
var tx = this.txQueue[tx_id];
tx.resultSet.push(data);
}
DroidDB.prototype.completeQuery = function(tx_id)
{
var tx = this.txQueue[tx_id];
var r = new result();
r.rows.resultSet = tx.resultSet;
r.rows.length = tx.resultSet.length;
tx.win(r);
}
DroidDB.prototype.fail = function(reason, tx_id)
{
var tx = this.txQueue[tx_id];
tx.fail(reason);
}
var DatabaseShell = function()
{
}
DatabaseShell.prototype.transaction = function(process)
{
tx = new Tx();
process(tx);
}
var Tx = function()
{
droiddb.txQueue.push(this);
this.id = droiddb.txQueue.length - 1;
this.resultSet = [];
}
Tx.prototype.executeSql = function(query, params, win, fail)
{
droidStorage.executeSql(query, params, this.id);
tx.win = win;
tx.fail = fail;
}
var result = function()
{
this.rows = new Rows();
}
var Rows = function()
{
this.resultSet = [];
this.length = 0;
}
Rows.prototype.item = function(row_id)
{
return this.resultSet[id];
}
var dbSetup = function(name, version, display_name, size)
{
droidStorage.openDatabase(name, version, display_name, size)
db_object = new DatabaseShell();
return db_object;
}
PhoneGap.addConstructor(function() {
if (typeof navigator.openDatabase == "undefined")
{
navigator.openDatabase = window.openDatabase = dbSetup;
window.droiddb = new DroidDB();
}
});

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/phonegap.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ponygap</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.phonegap.plugins"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name">
<activity android:name="ponygap"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,17 +0,0 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="ponygap" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked in in Version
Control Systems. -->
<property file="local.properties" />
<!-- The build.properties file can be created by you and is never touched
by the 'android' tool. This is the place to change some of the default property values
used by the Ant rules.
Here are some properties you may want to change/update:
application.package
the name of your application package as defined in the manifest. Used by the
'uninstall' rule.
source.dir
the name of the source directory. Default is 'src'.
out.dir
the name of the output directory. Default is 'bin'.
Properties related to the SDK location or the project target should be updated
using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems.
-->
<property file="build.properties" />
<!-- The default.properties file is created and updated by the 'android' tool, as well
as ADT.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems. -->
<property file="default.properties" />
<!-- Custom Android task to deal with the project target, and import the proper rules.
This requires ant 1.6.0 or above. -->
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<setup />
<target name="jar" depends="compile">
<jar jarfile="phonegap_plugins.jar" basedir="bin/classes" excludes="**/R*.class" />
</target>
</project>

Binary file not shown.

View File

@ -1,10 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked in Version Control Systems,
# as it contains information specific to your local configuration.
# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/home/bowserj/android-sdk-linux_x86-1.6_r1

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, ponygap"
/>
</LinearLayout>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ponygap</string>
</resources>

View File

@ -1,34 +0,0 @@
package com.phonegap.plugins;
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.webkit.WebView;
public class TtsManager {
TextToSpeech voice;
Context mCtx;
WebView appView;
TtsManager(WebView view, Context ctx)
{
mCtx = ctx;
appView = view;
voice = new TextToSpeech(mCtx, ttsInitListener);
}
public void say(String text)
{
voice.speak(text, 1, null);
}
//I have no idea why you would use this? Do you have predefined speech?
private TextToSpeech.OnInitListener ttsInitListener = new TextToSpeech.OnInitListener() {
public void onInit(int status) {
}
};
}

View File

@ -1,21 +0,0 @@
package com.phonegap.plugins;
import android.os.Bundle;
import com.phonegap.*;
public class ponygap extends DroidGap
{
/* Declare plugins here */
TtsManager tts;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
tts = new TtsManager(super.appView, this);
super.appView.addJavascriptInterface(tts, "ttsHook");
}
}