auto import from //branches/cupcake/...@127101

This commit is contained in:
The Android Open Source Project
2009-01-20 14:03:55 -08:00
parent b8d704a517
commit 7b53e39377
57 changed files with 1009 additions and 1269 deletions

View File

@@ -112,9 +112,7 @@ framework/swing-worker-1.1.jar tools/lib/swing-worker-1.1.jar
bin/traceview tools/traceview bin/traceview tools/traceview
framework/traceview.jar tools/lib/traceview.jar framework/traceview.jar tools/lib/traceview.jar
# activitycreator # custom ant tasks
bin/activitycreator tools/activitycreator
framework/activitycreator.jar tools/lib/activitycreator.jar
framework/anttasks.jar tools/lib/anttasks.jar framework/anttasks.jar tools/lib/anttasks.jar
# sdkmanager # sdkmanager

View File

@@ -87,7 +87,7 @@ function package() {
# Remove obsolete stuff from tools # Remove obsolete stuff from tools
TOOLS="$DEST/tools" TOOLS="$DEST/tools"
LIB="$DEST/tools/lib" LIB="$DEST/tools/lib"
rm -v "$TOOLS"/{aapt,aidl,adb,emulator,traceview,draw9patch,hierarchyviewer,dx,dexdump,apkbuilder,ddms,dmtracedump,mksdcard,sqlite3,activitycreator,android} rm -v "$TOOLS"/{aapt,aidl,adb,emulator,traceview,draw9patch,hierarchyviewer,dx,dexdump,apkbuilder,ddms,dmtracedump,mksdcard,sqlite3,android}
rm -v --force "$LIB"/*.so "$LIB"/*.jnilib rm -v --force "$LIB"/*.so "$LIB"/*.jnilib
# Copy all the new stuff in tools # Copy all the new stuff in tools
@@ -108,7 +108,6 @@ function package() {
cp -v development/tools/traceview/etc/traceview.bat "$TOOLS" cp -v development/tools/traceview/etc/traceview.bat "$TOOLS"
cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS" cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"
cp -v development/tools/draw9patch/etc/draw9patch.bat "$TOOLS" cp -v development/tools/draw9patch/etc/draw9patch.bat "$TOOLS"
cp -v development/tools/activitycreator/etc/activitycreator.bat "$TOOLS"
cp -v development/tools/sdkmanager/app/etc/android.bat "$TOOLS" cp -v development/tools/sdkmanager/app/etc/android.bat "$TOOLS"
# Fix EOL chars to make window users happy - fix all files at the top level only # Fix EOL chars to make window users happy - fix all files at the top level only

View File

@@ -48,7 +48,7 @@ pdk_docs_intermediates := $(call intermediates-dir-for,PACKAGING,pdkdocs)
pdk_templates_dir := development/pdk/docs pdk_templates_dir := development/pdk/docs
pdk_config_dir := development/pdk/doxygen_config pdk_config_dir := development/pdk/doxygen_config
pdk_docsfile_dir := $(pdk_config_dir)/docsfiles pdk_docsfile_dir := $(pdk_config_dir)/docsfiles
pdk_hardware_dir := hardware/libhardware/include/hardware pdk_legacy_hardware_dir := hardware/libhardware_legacy/include/hardware_legacy
pdk_camera_dir := frameworks/base/include/ui pdk_camera_dir := frameworks/base/include/ui
# Destination directory for docs (templates + doxygenated headers) # Destination directory for docs (templates + doxygenated headers)
@@ -74,9 +74,10 @@ doxygen_version = doxygen
# Header files to doxygenize. # Header files to doxygenize.
# Add new header files to document here, also adjust the templates to have # Add new header files to document here, also adjust the templates to have
# descriptions for the new headers and point to the new doxygen created html. # descriptions for the new headers and point to the new doxygen created html.
pdk_headers := $(pdk_hardware_dir)/AudioHardwareInterface.h \ pdk_headers := \
$(pdk_hardware_dir)/gps.h \ $(pdk_legacy_hardware_dir)/AudioHardwareInterface.h \
$(pdk_hardware_dir)/wifi.h \ $(pdk_legacy_hardware_dir)/gps.h \
$(pdk_legacy_hardware_dir)/wifi.h \
$(pdk_camera_dir)/CameraHardwareInterface.h $(pdk_camera_dir)/CameraHardwareInterface.h
# Create a rule to copy the list of PDK headers to be doxyginated. # Create a rule to copy the list of PDK headers to be doxyginated.

View File

@@ -66,3 +66,7 @@ The build target 'pdk' brings in the pdk/ndk make files into the build system.
pdk_docs - which builds the pdk documentation pdk_docs - which builds the pdk documentation
ndk - which builds the native development kit (native compiler, linker, etc.) ndk - which builds the native development kit (native compiler, linker, etc.)
pdk_all - which builds the above two targets pdk_all - which builds the above two targets
for doxygen version changing you can pass in the variable:
doxygen_version='<path/name_of_doxygen_executable>'
on the make line.

View File

@@ -0,0 +1,2 @@
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Doxygen-Generated Content</title>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<style type="text/css">
<!--
.navigation {
display: none;
}
-->
</style>
</head>
<body>

View File

@@ -16,7 +16,6 @@
package com.example.android.softkeyboard; package com.example.android.softkeyboard;
import android.content.Context;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView; import android.inputmethodservice.KeyboardView;
@@ -25,7 +24,6 @@ import android.util.Log;
import android.view.KeyCharacterMap; import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
@@ -44,6 +42,16 @@ public class SoftKeyboard extends InputMethodService
implements KeyboardView.OnKeyboardActionListener { implements KeyboardView.OnKeyboardActionListener {
static final boolean DEBUG = false; static final boolean DEBUG = false;
/**
* This boolean indicates the optional example code for performing
* processing of hard keys in addition to regular text generation
* from on-screen interaction. It would be used for input methods that
* perform language translations (such as converting text entered on
* a QWERTY keyboard to Chinese), but may not be used for input methods
* that are primarily intended to be used for on-screen text entry.
*/
static final boolean PROCESS_HARD_KEYS = true;
private KeyboardView mInputView; private KeyboardView mInputView;
private CandidateView mCandidateView; private CandidateView mCandidateView;
private CompletionInfo[] mCompletions; private CompletionInfo[] mCompletions;
@@ -62,13 +70,17 @@ public class SoftKeyboard extends InputMethodService
private String mWordSeparators; private String mWordSeparators;
/**
* Helper function to generate the various keyboard layouts used by the
* input method. Takes care of regenerating the layouts if the width
* of the input method changes.
*/
private void makeKeyboards() { private void makeKeyboards() {
// Configuration change is coming after the keyboard gets recreated. So don't rely on that.
// If keyboards have already been made, check if we have a screen width change and
// create the keyboard layouts again at the correct orientation
if (mQwertyKeyboard != null) { if (mQwertyKeyboard != null) {
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // Configuration changes can happen after the keyboard gets recreated,
int displayWidth = wm.getDefaultDisplay().getWidth(); // so we need to be able to re-build the keyboards if the available
// space has changed.
int displayWidth = getMaxWidth();
if (displayWidth == mLastDisplayWidth) return; if (displayWidth == mLastDisplayWidth) return;
mLastDisplayWidth = displayWidth; mLastDisplayWidth = displayWidth;
} }
@@ -77,14 +89,25 @@ public class SoftKeyboard extends InputMethodService
mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift); mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols_shift);
} }
/**
* Main initialization of the input method component. Be sure to call
* to super class.
*/
@Override public void onCreate() { @Override public void onCreate() {
super.onCreate(); super.onCreate();
makeKeyboards(); makeKeyboards();
mWordSeparators = getResources().getString(R.string.word_separators); mWordSeparators = getResources().getString(R.string.word_separators);
} }
@Override /**
public View onCreateInputView() { * Called by the framework when your view for creating input needs to
* be generated. This will be called the first time your input method
* is displayed, and every time it needs to be re-created such as due to
* a configuration change.
*/
@Override public View onCreateInputView() {
// We call makeKeyboards() here to regenerate them if needed due to
// a configuration change.
makeKeyboards(); makeKeyboards();
mInputView = (KeyboardView) getLayoutInflater().inflate( mInputView = (KeyboardView) getLayoutInflater().inflate(
R.layout.input, null); R.layout.input, null);
@@ -93,15 +116,27 @@ public class SoftKeyboard extends InputMethodService
return mInputView; return mInputView;
} }
@Override /**
public View onCreateCandidatesView() { * Called by the framework when your view for showing candidates needs to
* be generated, like {@link #onCreateInputView}.
*/
@Override public View onCreateCandidatesView() {
mCandidateView = new CandidateView(this); mCandidateView = new CandidateView(this);
mCandidateView.setService(this); mCandidateView.setService(this);
return mCandidateView; return mCandidateView;
} }
@Override /**
public void onStartInputView(EditorInfo attribute, boolean restarting) { * This is the main point where we do our initialization of the input method
* to begin operating on an application. At this point we have been
* bound to the client, and are now receiving all of the detailed information
* about the target of our edits.
*/
@Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
super.onStartInputView(attribute, restarting);
// Reset our state. We want to do this even if restarting, because
// the underlying state of the text editor could have changed in any way.
mComposing.setLength(0); mComposing.setLength(0);
updateCandidates(); updateCandidates();
@@ -114,57 +149,105 @@ public class SoftKeyboard extends InputMethodService
mCompletionOn = false; mCompletionOn = false;
mCompletions = null; mCompletions = null;
Keyboard keyboard; Keyboard keyboard;
// We are now going to initialize our state based on the type of
// text being edited.
switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) { switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) {
case EditorInfo.TYPE_CLASS_NUMBER: case EditorInfo.TYPE_CLASS_NUMBER:
case EditorInfo.TYPE_CLASS_DATETIME: case EditorInfo.TYPE_CLASS_DATETIME:
// Numbers and dates default to the symbols keyboard, with
// no extra features.
keyboard = mSymbolsKeyboard; keyboard = mSymbolsKeyboard;
break; break;
case EditorInfo.TYPE_CLASS_PHONE: case EditorInfo.TYPE_CLASS_PHONE:
// Phones will also default to the symbols keyboard, though
// often you will want to have a dedicated phone keyboard.
keyboard = mSymbolsKeyboard; keyboard = mSymbolsKeyboard;
break; break;
default:
case EditorInfo.TYPE_CLASS_TEXT:
// This is general text editing. We will default to the
// normal alphabetic keyboard, and assume that we should
// be doing predictive text (showing candidates as the
// user types).
keyboard = mQwertyKeyboard; keyboard = mQwertyKeyboard;
mPredictionOn = true; mPredictionOn = true;
// Make sure that passwords are not displayed in candidate view
// We now look for a few special variations of text that will
// modify our behavior.
int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION; int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION;
if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) { if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD) {
// Do not display predictions / what the user is typing
// when they are entering a password.
mPredictionOn = false; mPredictionOn = false;
} }
if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| variation == EditorInfo.TYPE_TEXT_VARIATION_URI) { || variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
// Our predictions are not useful for e-mail addresses
// or URIs.
mPredictionOn = false; mPredictionOn = false;
} }
if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
// If this is an auto-complete text view, then our predictions
// will not be shown and instead we will allow the editor
// to supply their own. We only show the editor's
// candidates when in fullscreen mode, otherwise relying
// own it displaying its own UI.
mPredictionOn = false; mPredictionOn = false;
mCompletionOn = isFullscreenMode(); mCompletionOn = isFullscreenMode();
} }
// We also want to look at the current state of the editor
// to decide whether our alphabetic keyboard should start out
// shifted.
updateShiftKeyState(attribute); updateShiftKeyState(attribute);
break; break;
default:
// For all unknown input types, default to the alphabetic
// keyboard with no special features.
keyboard = mQwertyKeyboard;
} }
// Apply the selected keyboard to the input view.
if (mInputView != null) { if (mInputView != null) {
mInputView.setKeyboard(keyboard); mInputView.setKeyboard(keyboard);
mInputView.closing(); mInputView.closing();
} }
mComposing.setLength(0);
setSuggestions(null, false, false);
} }
@Override /**
public void onFinishInput() { * This is called when the user is done editing a field. We can use
* this to reset our state.
*/
@Override public void onFinishInput() {
super.onFinishInput(); super.onFinishInput();
// Clear current composing text and candidates.
mComposing.setLength(0); mComposing.setLength(0);
updateCandidates(); updateCandidates();
// We only hide the candidates window when finishing input on
// a particular editor, to avoid popping the underlying application
// up and down if the user is entering text into the bottom of
// its window.
setCandidatesViewShown(false);
if (mInputView != null) { if (mInputView != null) {
mInputView.closing(); mInputView.closing();
} }
} }
@Override /**
public void onUpdateSelection(int oldSelStart, int oldSelEnd, * Deal with the editor reporting movement of its cursor.
*/
@Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd, int newSelStart, int newSelEnd,
int candidatesStart, int candidatesEnd) { int candidatesStart, int candidatesEnd) {
// If the current selection in the text view changes, we should // If the current selection in the text view changes, we should
// clear whatever candidate text we have. // clear whatever candidate text we have.
if (mComposing.length() > 0 && (newSelStart != candidatesEnd if (mComposing.length() > 0 && (newSelStart != candidatesEnd
@@ -178,8 +261,13 @@ public class SoftKeyboard extends InputMethodService
} }
} }
@Override /**
public void onDisplayCompletions(CompletionInfo[] completions) { * This tells us about completions that the editor has determined based
* on the current text in it. We want to use this in fullscreen mode
* to show the completions ourself, since the editor can not be seen
* in that situation.
*/
@Override public void onDisplayCompletions(CompletionInfo[] completions) {
if (mCompletionOn) { if (mCompletionOn) {
mCompletions = completions; mCompletions = completions;
if (completions == null) { if (completions == null) {
@@ -196,6 +284,11 @@ public class SoftKeyboard extends InputMethodService
} }
} }
/**
* This translates incoming hard key events in to edit operations on an
* InputConnection. It is only needed when using the
* PROCESS_HARD_KEYS option.
*/
private boolean translateKeyDown(int keyCode, KeyEvent event) { private boolean translateKeyDown(int keyCode, KeyEvent event) {
mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState, mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
keyCode, event); keyCode, event);
@@ -228,55 +321,71 @@ public class SoftKeyboard extends InputMethodService
return true; return true;
} }
@Override /**
public boolean onKeyDown(int keyCode, KeyEvent event) { * Use this to monitor key events being delivered to the application.
* We get first crack at them, and can either resume them or let them
* continue to the app.
*/
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_BACK: case KeyEvent.KEYCODE_BACK:
// The InputMethodService already takes care of the back
// key for us, to dismiss the input method if it is shown.
// However, our keyboard could be showing a pop-up window
// that back should dismiss, so we first allow it to do that.
if (event.getRepeatCount() == 0 && mInputView != null) { if (event.getRepeatCount() == 0 && mInputView != null) {
if (mInputView.handleBack()) { if (mInputView.handleBack()) {
return true; return true;
} }
} }
break; break;
case KeyEvent.KEYCODE_DEL: case KeyEvent.KEYCODE_DEL:
// Special handling of the delete key: if we currently are
// composing text for the user, we want to modify that instead
// of let the application to the delete itself.
if (mComposing.length() > 0) { if (mComposing.length() > 0) {
onKey(Keyboard.KEYCODE_DELETE, null); onKey(Keyboard.KEYCODE_DELETE, null);
return true; return true;
} }
break; break;
default: default:
if (mPredictionOn && translateKeyDown(keyCode, event)) { // For all other keys, if we want to do transformations on
return true; // text being entered with a hard keyboard, we need to process
// it and do the appropriate action.
if (PROCESS_HARD_KEYS) {
if (mPredictionOn && translateKeyDown(keyCode, event)) {
return true;
}
} }
} }
return super.onKeyDown(keyCode, event); return super.onKeyDown(keyCode, event);
} }
@Override /**
public boolean onKeyUp(int keyCode, KeyEvent event) { * Use this to monitor key events being delivered to the application.
switch (keyCode) { * We get first crack at them, and can either resume them or let them
case KeyEvent.KEYCODE_DPAD_DOWN: * continue to the app.
case KeyEvent.KEYCODE_DPAD_UP: */
case KeyEvent.KEYCODE_DPAD_LEFT: @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
case KeyEvent.KEYCODE_DPAD_RIGHT: // If we want to do transformations on text being entered with a hard
// Enable shift key and DPAD to do selections // keyboard, we need to process the up events to update the meta key
if (mInputView != null && mInputView.isShown() && mInputView.isShifted()) { // state we are tracking.
event = new KeyEvent(event.getDownTime(), event.getEventTime(), if (PROCESS_HARD_KEYS) {
event.getAction(), event.getKeyCode(), event.getRepeatCount(), if (mPredictionOn) {
KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
getCurrentInputConnection().sendKeyEvent(event); keyCode, event);
return true; }
}
break;
default:
if (mPredictionOn) {
mMetaState = MetaKeyKeyListener.handleKeyUp(mMetaState,
keyCode, event);
}
} }
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
} }
/**
* Helper function to commit any text being composed in to the editor.
*/
private void commitTyped(InputConnection inputConnection) { private void commitTyped(InputConnection inputConnection) {
if (mComposing.length() > 0) { if (mComposing.length() > 0) {
inputConnection.commitText(mComposing, mComposing.length()); inputConnection.commitText(mComposing, mComposing.length());
@@ -285,7 +394,11 @@ public class SoftKeyboard extends InputMethodService
} }
} }
public void updateShiftKeyState(EditorInfo attr) { /**
* Helper to update the shift state of our keyboard based on the initial
* editor state.
*/
private void updateShiftKeyState(EditorInfo attr) {
if (attr != null if (attr != null
&& mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) { && mInputView != null && mQwertyKeyboard == mInputView.getKeyboard()) {
int caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType); int caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
@@ -293,6 +406,9 @@ public class SoftKeyboard extends InputMethodService
} }
} }
/**
* Helper to determine if a given character code is alphabetic.
*/
private boolean isAlphabet(int code) { private boolean isAlphabet(int code) {
if (Character.isLetter(code)) { if (Character.isLetter(code)) {
return true; return true;
@@ -301,6 +417,9 @@ public class SoftKeyboard extends InputMethodService
} }
} }
/**
* Helper to send a key down / key up pair to the current editor.
*/
private void keyDownUp(int keyEventCode) { private void keyDownUp(int keyEventCode) {
getCurrentInputConnection().sendKeyEvent( getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode)); new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
@@ -308,6 +427,9 @@ public class SoftKeyboard extends InputMethodService
new KeyEvent(KeyEvent.ACTION_UP, keyEventCode)); new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
} }
/**
* Helper to send a character to the editor as raw key events.
*/
private void sendKey(int keyCode) { private void sendKey(int keyCode) {
switch (keyCode) { switch (keyCode) {
case '\n': case '\n':
@@ -378,13 +500,13 @@ public class SoftKeyboard extends InputMethodService
public void setSuggestions(List<String> suggestions, boolean completions, public void setSuggestions(List<String> suggestions, boolean completions,
boolean typedWordValid) { boolean typedWordValid) {
mCandidateView.setSuggestions(suggestions, completions, typedWordValid); if (mCandidateView != null) {
if (suggestions != null && suggestions.size() > 0) { mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
setCandidatesViewShown(true); if (suggestions != null && suggestions.size() > 0) {
} else if (isFullscreenMode()) { setCandidatesViewShown(true);
setCandidatesViewShown(true); } else if (isFullscreenMode()) {
} else { setCandidatesViewShown(true);
setCandidatesViewShown(false); }
} }
} }
@@ -399,7 +521,6 @@ public class SoftKeyboard extends InputMethodService
getCurrentInputConnection().commitText("", 0); getCurrentInputConnection().commitText("", 0);
updateCandidates(); updateCandidates();
} else { } else {
//getCurrentInputConnection().deleteSurroundingText(1, 0);
keyDownUp(KeyEvent.KEYCODE_DEL); keyDownUp(KeyEvent.KEYCODE_DEL);
} }
updateShiftKeyState(getCurrentInputEditorInfo()); updateShiftKeyState(getCurrentInputEditorInfo());
@@ -439,7 +560,7 @@ public class SoftKeyboard extends InputMethodService
updateCandidates(); updateCandidates();
} else { } else {
getCurrentInputConnection().commitText( getCurrentInputConnection().commitText(
String.valueOf((char) primaryCode), 0); String.valueOf((char) primaryCode), 1);
} }
} }
@@ -459,7 +580,7 @@ public class SoftKeyboard extends InputMethodService
} }
} }
protected String getWordSeparators() { private String getWordSeparators() {
return mWordSeparators; return mWordSeparators;
} }
@@ -504,10 +625,11 @@ public class SoftKeyboard extends InputMethodService
} }
public void swipeUp() { public void swipeUp() {
// ?
} }
public void onPress(int primaryCode) { } public void onPress(int primaryCode) {
}
public void onRelease(int primaryCode) { } public void onRelease(int primaryCode) {
}
} }

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>ActivityCreator</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,17 +0,0 @@
# Copyright (C) 2007 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ACTIVITY_CREATOR_LOCAL_DIR := $(call my-dir)
include $(ACTIVITY_CREATOR_LOCAL_DIR)/etc/Android.mk
include $(ACTIVITY_CREATOR_LOCAL_DIR)/src/Android.mk

View File

@@ -1,20 +0,0 @@
# Copyright (C) 2007 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PREBUILT_EXECUTABLES := activitycreator
include $(BUILD_HOST_PREBUILT)

View File

@@ -1,20 +0,0 @@
#!/bin/sh
# Copyright (C) 2007 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TOOLS_DIR=`dirname $0`
AC_JARFILE=$TOOLS_DIR/lib/activitycreator.jar
java -Dcom.android.activitycreator.toolsdir=$TOOLS_DIR -cp $AC_JARFILE com.android.activitycreator.ActivityCreator "$@"

View File

@@ -1,22 +0,0 @@
@echo off
rem Copyright (C) 2007 The Android Open Source Project
rem
rem Licensed under the Apache License, Version 2.0 (the "License");
rem you may not use this file except in compliance with the License.
rem You may obtain a copy of the License at
rem
rem http://www.apache.org/licenses/LICENSE-2.0
rem
rem Unless required by applicable law or agreed to in writing, software
rem distributed under the License is distributed on an "AS IS" BASIS,
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem See the License for the specific language governing permissions and
rem limitations under the License.
rem don't modify the caller's environmeny
setlocal
set toolsdir=%~dp0\
set acjarfile=%toolsdir%/lib/activitycreator.jar
call java -Dcom.android.activitycreator.toolsdir="%toolsdir%" -cp "%acjarfile%" com.android.activitycreator.ActivityCreator %*

View File

@@ -1,23 +0,0 @@
# Copyright (C) 2007 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := activitycreator
include $(BUILD_HOST_JAVA_LIBRARY)

View File

@@ -1,881 +0,0 @@
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.activitycreator;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
/**
* Creates the basic files needed to get an Android project up and running. Also
* allows creation of IntelliJ project files.
*
* @hide
*/
public class ActivityCreator {
// FIXME: target platform must be provided by the user
private final String mTargetPlatform = "android-1.1";
/** Whether we are in silent mode (i.e.: don't print any non-error messages) */
private boolean mSilent;
/** Path to tools */
private String mToolsDir;
/** Path to SDK */
private String mSdkDir;
/** Path to target platform's template folder */
private String mTemplateDir;
/** Path to tools/lib for the build templates */
private String mLibDir;
/** Path to output */
private String mOutDir;
/** IDE to generate for */
private String mIde;
/** Data used for the "alias" mode */
private String mAliasData;
/** Application label used in the "alias" mode */
private String mApplicationLabel;
/** Package of Activity */
private String mPackageFull;
/**
* Constructs object.
* @param args arguments passed to the program
*/
public ActivityCreator(String[] args) {
mSilent = false;
mIde = "";
initPathVars();
parseArgs(args);
if (isAliasProject()) {
setupAliasProject();
} else {
setupProject();
}
}
/**
* Initializes the path variables based on location of this class.
*/
private void initPathVars() {
/* We get passed a property for the tools dir */
String toolsDirProp = System.getProperty("com.android.activitycreator.toolsdir");
if (toolsDirProp == null) {
// for debugging, it's easier to override using the process environment
toolsDirProp = System.getenv("com.android.activitycreator.toolsdir");
}
if (toolsDirProp == null) {
printHelpAndExit("ERROR: The tools directory property is not set, please make sure you are executing activitycreator or activitycreator.bat");
}
/* Absolute path */
File toolsDir = new File(toolsDirProp);
try {
mToolsDir = toolsDir.getCanonicalPath();
} catch (IOException e) {
printHelpAndExit("ERROR: Could not determine the tools directory.");
}
toolsDir = new File(mToolsDir);
mSdkDir = toolsDir.getParent();
mLibDir = mToolsDir + File.separator + "lib";
mTemplateDir = mSdkDir + File.separator + "platforms" + File.separator +
mTargetPlatform + File.separator + "templates";
try {
mOutDir = new File("").getCanonicalPath();
} catch (IOException e) {
printHelpAndExit("ERROR: Could not determine the current directory.");
}
if (!toolsDir.exists()) {
printHelpAndExit("ERROR: Tools directory does not exist.");
}
if (!(new File(mSdkDir).exists())) {
printHelpAndExit("ERROR: SDK directory does not exist.");
}
if (!(new File(mTemplateDir).exists())) {
printHelpAndExit("ERROR: Target platform templates directory does not exist.");
}
if (!(new File(mLibDir).exists())) {
printHelpAndExit("ERROR: Library directory does not exist.");
}
}
/**
* Parses command-line arguments, or prints help/usage and exits if error.
* @param args arguments passed to the program
*/
private void parseArgs(String[] args) {
final int numArgs = args.length;
try {
int argPos = 0;
for (; argPos < numArgs; argPos++) {
final String arg = args[argPos];
if (arg.equals("-o") || arg.equals("-out") || arg.equals("--out")) {
argPos++;
mOutDir = args[argPos];
} else if (arg.equals("-d") || arg.equals("-data") || arg.equals("--data")) {
argPos++;
mAliasData = args[argPos];
} else if (arg.equals("-l") || arg.equals("-label") || arg.equals("--label")) {
argPos++;
mApplicationLabel = args[argPos];
} else if (arg.equals("-i") || arg.equals("-ide") || arg.equals("--ide")) {
argPos++;
mIde = args[argPos].toLowerCase();
} else if (arg.equals("-h") || arg.equals("-help") || arg.equals("--help")) {
printHelpAndExit(null);
} else if (arg.equals("-s") || arg.equals("-silent") || arg.equals("--silent")) {
mSilent = true;
} else {
if (mPackageFull == null) {
mPackageFull = extractPackageFromManifest(args[argPos]);
if (mPackageFull == null) {
mPackageFull = args[argPos];
}
} else {
/* Package has already been set, so this is an extra argument */
printHelpAndExit("ERROR: Too many arguments: %1$s", args[argPos]);
}
}
}
} catch (ArrayIndexOutOfBoundsException e) {
/* Any OOB triggers help */
printHelpAndExit("ERROR: Not enough arguments.");
}
if (isStringEmpty(mPackageFull)) {
printHelpAndExit("ERROR: Please enter a package.");
}
if (isStringEmpty(mOutDir)) {
printHelpAndExit("ERROR: Please enter an output directory.");
}
// we need both application label and url for the "alias" mode
if (isStringEmpty(mAliasData) ^ isStringEmpty(mApplicationLabel)) {
printHelpAndExit("ERROR: Alias projects require both --data and --label.");
}
if (mIde.equals("eclipse")) {
printHelpAndExit("ERROR: For Eclipse support, please install the Eclipse ADT plugin and use its New Project Wizard.");
}
}
/**
* Prints the help/usage and exits.
* @param errorFormat Optional error message to print prior to usage using String.format
* @param args Arguments for String.format
*/
private void printHelpAndExit(String errorFormat, Object... args) {
if (errorFormat != null) {
System.err.println(String.format(errorFormat, args));
}
/*
* usage should fit in 80 columns
* 12345678901234567890123456789012345678901234567890123456789012345678901234567890
*/
final String usage = "\n" +
"Activity Creator Script.\n" +
"\n" +
"Usage:\n" +
" activitycreator --out outdir [--ide intellij] your.package.name.ActivityName\n" +
" activitycreator --out outdir [--ide intellij] path/to/AndroidManifest.xml\n" +
" activitycreator --out outdir --data data --label app_label your.package.name\n" +
"\n" +
"With both the --data and --label options, ActivityCreator creates the structure\n" +
"of an 'alias' Android application.\n" +
" An Alias project is an application with no code that simply launches an\n" +
" android.intent.action.VIEW intent with the provided data.\n" +
" The following will be created (existing files will not be modified):\n" +
" - AndroidManifest.xml: The application manifest file.\n" +
" - build.xml: An Ant script to build/package the application.\n" +
" - res/values/strings.xml: an XML file defining the application label\n" +
" string resource.\n" +
" - res/xml/alias.xml: an XML file defining the VIEW intent and its data.\n " +
"\n" +
"Without --data and --label, ActivityCreator creates the structure of a minimal\n" +
"Android application.\n" +
" The following will be created (existing files will not be modified):\n" +
" - AndroidManifest.xml: The application manifest file.\n" +
" - build.xml: An Ant script to build/package the application.\n" +
" - res : The resource directory.\n" +
" - src : The source directory.\n" +
" - src/your/package/name/ActivityName.java the Activity java class.\n" +
" packageName is a fully qualified java Package in the format\n" +
" <package1>.<package2>... (with at least two components).\n" +
" - bin : The output folder for the build script.\n" +
"\n" +
"Options:\n" +
" -o <folder>, --out <folder>\n" +
" Specifies where to create the files/folders.\n" +
" -i intellij, --ide intellij\n" +
" Creates project files for IntelliJ (non alias application only)\n" +
" -d <data-string>, --data <data-string>\n" +
" The data passed to the VIEW intent. For instance, this can be a url,\n" +
" such as http://www.android.com\n" +
" -l <app-label>, --label <app-label>\n" +
" The name the alias application will have in the HOME screen.\n" +
" -h, --help\n" +
" Display this help.\n" +
" -s, --silent\n" +
" Silent mode.\n" +
"\n" +
"For Eclipse support, please use the ADT plugin.\n";
println(usage);
System.exit(1);
}
/**
* Installs a destination file that is based on a code template file at the source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
* Invokes {@link #installProjectTemplate(String, String, Map, boolean, String)} with
* the main project output directory (#mOutDir) as the last argument.
*
* @param source the name of to the source template file
* @param dest the path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
*
* @see #installProjectTemplate(String, String, Map, boolean, String)
*/
private void installProjectTemplate(String source, String dest,
Map<String, String> keywords, boolean force) {
installProjectTemplate(source, dest, keywords, force, mOutDir);
}
/**
* Installs a destination file that is based on a code template file at the source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
* @param source the name of to the source template file
* @param dest the path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
* @param outDir the output directory to copy the template file to
*/
private void installProjectTemplate(String source, String dest,
Map<String, String> keywords, boolean force, String outDir) {
final String sourcePath = mTemplateDir + File.separator + source;
final String destPath = outDir + File.separator + dest;
installFullPathTemplate(sourcePath, destPath, keywords, force);
}
/**
* Installs a destination file that is based on a build template file at the source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
* Invokes {@link #installBuildTemplate(String, String, Map, boolean, String)} with
* the main project output directory (#mOutDir) as the last argument.
*
* @param source the name of to the source template file
* @param dest the path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
*
* @see #installBuildTemplate(String, String, Map, boolean, String)
*/
private void installBuildTemplate(String source, String dest,
Map<String, String> keywords, boolean force) {
installBuildTemplate(source, dest, keywords, force, mOutDir);
}
/**
* Installs a destination file that is based on a build template file at the source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
* @param source the name of to the source template file
* @param dest the path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
* @param outDir the output directory to copy the template file to
*/
private void installBuildTemplate(String source, String dest,
Map<String, String> keywords, boolean force, String outDir) {
final String sourcePath = mLibDir + File.separator + source;
final String destPath = outDir + File.separator + dest;
installFullPathTemplate(sourcePath, destPath, keywords, force);
}
/**
* Installs a destination file that is based on the template file at source.
* For each match of each key in keywords will be replaced with its
* corresponding value in the destination file.
*
* @param sourcePath the full path to the source template file
* @param destPath the full path to the destination file
* @param keywords in the destination file, the keys will be replaced by their values
* @param force True to force writing the file even if it already exists
*/
private void installFullPathTemplate(String sourcePath, String destPath,
Map<String, String> keywords, boolean force) {
final File destPathFile = new File(destPath);
if (!force && destPathFile.exists()) {
println("WARNING! The file %1$s already exists and will not be overwritten!\n",
destPathFile.getName());
return;
}
try {
BufferedWriter out = new BufferedWriter(new FileWriter(destPathFile));
BufferedReader in = new BufferedReader(new FileReader(sourcePath));
String line;
while ((line = in.readLine()) != null) {
for (String key : keywords.keySet()) {
line = line.replace(key, keywords.get(key));
}
out.write(line);
out.newLine();
}
out.close();
in.close();
} catch (Exception e) {
printHelpAndExit("ERROR: Could not access %1$s: %2$s", destPath, e.getMessage());
}
println("Added file %1$s", destPath);
}
/**
* Set up the Android-related files
*/
private void setupProject() {
String packageName = null;
String activityName = null;
String activityTestName = null;
try {
/* Grab package and Activity names */
int lastPeriod = mPackageFull.lastIndexOf('.');
packageName = mPackageFull.substring(0, lastPeriod);
if (lastPeriod < mPackageFull.length() - 1) {
activityName = mPackageFull.substring(lastPeriod+1);
activityTestName = activityName + "Test";
}
if (packageName.indexOf('.') == -1) {
printHelpAndExit("ERROR: Package name must be composed of at least two java identifiers.");
}
} catch (RuntimeException e) {
printHelpAndExit("ERROR: Invalid package or activity name.");
}
println("Package: %1$s", packageName);
println("Output directory: %1$s", mOutDir);
String testsOutDir = mOutDir + File.separator + "tests";
println("Tests directory: %1$s", testsOutDir);
if (activityName != null) {
println("Activity name: %1$s", activityName);
}
if (activityTestName != null) {
println("ActivityTest name: %1$s", activityTestName);
}
final HashMap<String, String> keywords = createBaseKeywordMap();
addTargetKeywords(keywords);
keywords.put("PACKAGE", packageName);
if (activityName != null) {
keywords.put("ACTIVITY_NAME", activityName);
}
final String packagePath =
stripString(packageName.replace(".", File.separator),
File.separatorChar);
keywords.put("PACKAGE_PATH", packagePath);
/* Other files that are always created */
/* Make Activity java file */
final String srcDir = "src" + File.separator + packagePath;
createDirs(srcDir);
if (isDirEmpty(srcDir, "Java") && activityName != null) {
installProjectTemplate("java_file.template", srcDir + File.separator
+ activityName + ".java", keywords, false /*force*/);
}
createDirs("bin");
createDirs("libs");
createDirs("res");
/* Make ActivityTest java file */
createDirs(srcDir, testsOutDir);
if (isDirEmpty(srcDir, "Java", testsOutDir) && activityTestName != null) {
installProjectTemplate("java_tests_file.template", srcDir + File.separator
+ activityTestName + ".java", keywords, false, testsOutDir);
}
createDirs("bin", testsOutDir);
createDirs("libs", testsOutDir);
createDirs("res", testsOutDir);
/* Make res files */
final String valuesDir = "res" + File.separator + "values";
createDirs(valuesDir);
if (isDirEmpty(valuesDir, "Resource Values")) {
installProjectTemplate("strings.template", valuesDir + File.separator
+ "strings.xml", keywords, false /*force*/);
}
final String layoutDir = "res" + File.separator + "layout";
createDirs(layoutDir);
if (isDirEmpty(layoutDir, "Resource Layout")) {
installProjectTemplate("layout.template", layoutDir + File.separator
+ "main.xml", keywords, false /*force*/);
}
/* Make AndroidManifest.xml and build.xml files */
installProjectTemplate("AndroidManifest.template", "AndroidManifest.xml",
keywords, false /*force*/);
installBuildTemplate("build.template", "build.xml", keywords, false /*force*/);
installBuildTemplate("default.properties.template", "default.properties", keywords,
true /*force*/);
/* Make AndroidManifest.xml and build.xml files for tests */
installProjectTemplate("AndroidManifest.tests.template", "AndroidManifest.xml",
keywords, false /*force*/, testsOutDir);
installBuildTemplate("build.template", "build.xml", keywords, false /*force*/, testsOutDir);
installBuildTemplate("default.properties.template", "default.properties", keywords,
true /*force*/, testsOutDir);
if (mIde.equals("intellij")) {
/* IntelliJ files */
if (activityName != null) {
installProjectTemplate("iml.template", activityName + ".iml", keywords,
false /*force*/);
installProjectTemplate("ipr.template", activityName + ".ipr", keywords,
false /*force*/);
installProjectTemplate("iws.template", activityName + ".iws", keywords,
false /*force*/);
}
} else if (!isStringEmpty(mIde)) {
println("WARNING: Unknown IDE option \"%1$s\". No IDE files generated.",
mIde);
}
}
/**
* Sets up the files for an alias project.
*/
private void setupAliasProject() {
println("Package: %1$s", mPackageFull);
println("Output directory: %1$s", mOutDir);
println("URL: %1$s", mAliasData);
println("Application label: %1$s", mApplicationLabel);
if (mIde != null) {
println("Alias project: ignoring --ide option.");
}
final HashMap<String, String> keywords = createBaseKeywordMap();
keywords.put("PACKAGE", mPackageFull);
keywords.put("ALIASDATA", mAliasData);
// since strings.xml uses ACTIVITY_NAME for the application label we use it as well.
// since we'll use a different AndroidManifest template this is not a problem.
keywords.put("ACTIVITY_NAME", mApplicationLabel);
/* Make res files */
final String xmlDir = "res" + File.separator + "xml";
createDirs(xmlDir);
if (isDirEmpty(xmlDir, "Resource Xml")) {
installProjectTemplate("alias.template", xmlDir + File.separator + "alias.xml",
keywords, false /*force*/);
}
final String valuesDir = "res" + File.separator + "values";
createDirs(valuesDir);
if (isDirEmpty(valuesDir, "Resource Values")) {
installProjectTemplate("strings.template", valuesDir + File.separator
+ "strings.xml", keywords, false /*force*/);
}
/* Make AndroidManifest.xml and build.xml files */
installProjectTemplate("AndroidManifest.alias.template", "AndroidManifest.xml", keywords,
false /*force*/);
installBuildTemplate("build.alias.template", "build.xml", keywords, false /*force*/);
installBuildTemplate("default.properties.template", "default.properties", keywords, true /*force*/);
}
private HashMap<String, String> createBaseKeywordMap() {
final HashMap<String, String> keywords = new HashMap<String, String>();
// When the tools & sdk folder on Windows get written to a properties file,
// we need to transform \ in /, otherwise it gets interpreted as an escape character.
// This is OK since ant can understand / as a separator even under Windows.
// References:
// - http://ant.apache.org/manual/CoreTasks/property.html
// - http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html#load(java.io.InputStream)
keywords.put("ANDROID_SDK_TOOLS", mToolsDir.replace('\\', '/'));
keywords.put("ANDROID_SDK_FOLDER", mSdkDir.replace('\\', '/'));
return keywords;
}
private void addTargetKeywords(HashMap<String, String> keywords) {
// FIXME: get this from the target selection
keywords.put("TARGET_MODE", "platform");
keywords.put("TARGET_API", "1"); // this is potentially wrong but since it's only used
// when editing a project config, this is ok for now.
keywords.put("TARGET_NAME", "android"); // this is only used in add-on mode.
keywords.put("TARGET_FOLDER", mTargetPlatform);
keywords.put("TARGET_MODE", "platform");
}
/**
* Called first.
* @param args arguments passed to the program
*/
public static void main(String[] args) {
new ActivityCreator(args);
}
/**
* Prints a message unless silence is enabled.
* @param format Format for String.format
* @param args Arguments for String.format
*/
public void println(String format, Object... args) {
if (!mSilent) {
System.out.println(String.format(format, args));
}
}
/**
* Checks whether a string is "empty" (null or trimmed length == 0)
* @param s the string to check
* @return true if empty
*/
public static boolean isStringEmpty(String s) {
return (s == null) || (s.trim().length() == 0);
}
/**
* Creates the path in the output directory along with any parent paths
* that don't exist.
*
* Invokes ActivityCreator#createDirs(String, String) with
* the main project output directory (#mOutDir) as the last argument.
*
* @param path the directory out/path that is created.
*
* @see com.android.activitycreator.ActivityCreator#createDirs(String, String)
*/
public void createDirs(String path) {
createDirs(path, mOutDir);
}
/**
* Creates the path in the output directory along with any parent paths
* that don't exist.
*
* @param path the directory out/path that is created.
* @param dir the directory in which the path to be created
*/
public void createDirs(String path, String dir) {
final File pathFile = new File(dir + File.separator + path);
boolean existedBefore = true;
if (!pathFile.exists()) {
if (!pathFile.mkdirs()) {
printHelpAndExit("ERROR: Could not create directory: %1$s", pathFile);
}
existedBefore = false;
}
if (pathFile.isDirectory()) {
if (!pathFile.canWrite()) {
printHelpAndExit("ERROR: Path is not writable: %1$s", pathFile);
}
} else {
printHelpAndExit("ERROR: Path is not a directory: %1$s", pathFile);
}
if (!existedBefore) {
try {
println("Created directory %1$s", pathFile.getCanonicalPath());
} catch (IOException e) {
printHelpAndExit("ERROR: Could not determine canonical path of created directory");
}
}
}
/**
* Checks whether the path in the output directory is empty
*
* Invokes ActivityCreator#isDirEmpty(String, String, String) with
* the main project output directory (#mOutDir) as the last argument.
*
* @param path the out/path directory that is checked
* @param message the logical name for what this path points to (used in
* warning message)
* @return whether the directory is empty
* @see com.android.activitycreator.ActivityCreator#isDirEmpty(String, String, String)
*/
public boolean isDirEmpty(String path, String message) {
return isDirEmpty(path, message, mOutDir);
}
/**
* Checks whether the path in the output directory is empty
*
* @param path the out/path directory that is checked
* @param message the logical name for what this path points to (used in
* warning message)
* @param outDir the output director to check
* @return whether the directory is empty
*/
public boolean isDirEmpty(String path, String message, String outDir) {
File pathFile = new File(outDir + File.separator + path);
String[] pathListing = pathFile.list();
if ((pathListing != null) && (pathListing.length > 0)) {
println("WARNING: There are already some %1$s files present. None will be created!",
message);
return false;
}
return true;
}
/**
* Strips the string of beginning and trailing characters (multiple
* characters will be stripped, example stripString("..test...", '.')
* results in "test";
*
* @param s the string to strip
* @param strip the character to strip from beginning and end
* @return the stripped string or the empty string if everything is stripped.
*/
public static String stripString(String s, char strip) {
final int sLen = s.length();
int newStart = 0, newEnd = sLen - 1;
while (newStart < sLen && s.charAt(newStart) == strip) {
newStart++;
}
while (newEnd >= 0 && s.charAt(newEnd) == strip) {
newEnd--;
}
/*
* newEnd contains a char we want, and substring takes end as being
* exclusive
*/
newEnd++;
if (newStart >= sLen || newEnd < 0) {
return "";
}
return s.substring(newStart, newEnd);
}
/**
* Returns true if the project is an alias project.
* <p/>
* Alias projects require both the --url and the --label options.
* @return boolean true if the project requested is an alias project
*/
private boolean isAliasProject() {
return (!isStringEmpty(mAliasData) && !isStringEmpty(mApplicationLabel));
}
/**
* Extracts a "full" package & activity name from an AndroidManifest.xml.
* @param osManifestPath The OS path to the AndroidManifest.xml
* @return A full "package.ActivtyName" if this is a valid manifest,
* or "package." (with a dot at the end) if there's no activity,
* or null if there's no valid package namespace.
*/
private String extractPackageFromManifest(String osManifestPath) {
File f = new File(osManifestPath);
if (!f.isFile()) {
return null;
}
try {
final String nsPrefix = "android";
final String nsURI = "http://schemas.android.com/apk/res/android";
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
if (nsPrefix.equals(prefix)) {
return nsURI;
}
return XMLConstants.NULL_NS_URI;
}
public String getPrefix(String namespaceURI) {
if (nsURI.equals(namespaceURI)) {
return nsPrefix;
}
return null;
}
@SuppressWarnings("unchecked")
public Iterator getPrefixes(String namespaceURI) {
if (nsURI.equals(namespaceURI)) {
ArrayList<String> list = new ArrayList<String>();
list.add(nsPrefix);
return list.iterator();
}
return null;
}
});
InputSource source = new InputSource(new FileReader(osManifestPath));
String packageName = xpath.evaluate("/manifest/@package", source);
source = new InputSource(new FileReader(osManifestPath));
// Select the "android:name" attribute of all <activity> nodes but only if they
// contain a sub-node <intent-filter><action> with an "android:name" attribute which
// is 'android.intent.action.MAIN' and an <intent-filter><category> with an
// "android:name" attribute which is 'android.intent.category.LAUNCHER'
String expression = String.format("/manifest/application/activity" +
"[intent-filter/action/@%1$s:name='android.intent.action.MAIN' and " +
"intent-filter/category/@%1$s:name='android.intent.category.LAUNCHER']" +
"/@%1$s:name", nsPrefix);
NodeList activityNames = (NodeList) xpath.evaluate(expression, source,
XPathConstants.NODESET);
// If we get here, both XPath expressions were valid so we're most likely dealing
// with an actual AndroidManifest.xml file. The nodes may not have the requested
// attributes though, if which case we should warn.
if (packageName == null || packageName.length() == 0) {
printHelpAndExit("ERROR: missing <manifest package=\"...\"> in '%1$s'",
osManifestPath);
}
// Get the first activity that matched earlier. If there is no activity,
// activityName is set to an empty string and the generated "combined" name
// will be in the form "package." (with a dot at the end).
String activityName = "";
if (activityNames.getLength() > 0) {
activityName = activityNames.item(0).getNodeValue();
}
if (!mSilent && activityNames.getLength() > 1) {
println("WARNING: There is more than one activity defined in '%1$s'.\n" +
"Only the first one will be used. If this is not appropriate, you need\n" +
"to specify one of these values manually instead:",
osManifestPath);
for (int i = 0; i < activityNames.getLength(); i++) {
String name = activityNames.item(i).getNodeValue();
name = combinePackageActivityNames(packageName, name);
println("- %1$s", name);
}
}
if (!mSilent && activityName.length() == 0) {
println("WARNING: missing <activity %1$s:name=\"...\"> in '%2$s'.\n" +
"No activity will be generated.",
nsPrefix, osManifestPath);
}
return combinePackageActivityNames(packageName, activityName);
} catch (IOException e) {
printHelpAndExit("ERROR: failed to read '%1$s', %2$s", osManifestPath, e.getMessage());
} catch (XPathExpressionException e) {
Throwable t = e.getCause();
printHelpAndExit("ERROR: failed to parse '%1$s', %2$s", osManifestPath,
t == null ? e.getMessage() : t.getMessage());
}
return null;
}
private String combinePackageActivityNames(String packageName,
String activityName) {
// Activity Name can have 3 forms:
// - ".Name" means this is a class name in the given package name.
// The full FQCN is thus packageName + ".Name"
// - "Name" is an older variant of the former. Full FQCN is packageName + "." + "Name"
// - "com.blah.Name" is a full FQCN. Ignore packageName and use activityName as-is.
// To be valid, the package name should have at least two components. This is checked
// later during the creation of the build.xml file, so we just need to detect there's
// a dot but not at pos==0.
int pos = activityName.indexOf('.');
if (pos == 0) {
return packageName + activityName;
} else if (pos > 0) {
return activityName;
} else {
return packageName + "." + activityName;
}
}
}

View File

@@ -56,47 +56,15 @@ public final class AndroidLocation {
*/ */
public final static String getFolder() throws AndroidLocationException { public final static String getFolder() throws AndroidLocationException {
if (sPrefsLocation == null) { if (sPrefsLocation == null) {
String osName = System.getProperty("os.name"); String home = findValidPath("user.home", "HOME");
// First we check for unknown or non windows OS.
if (osName == null || osName.startsWith("Windows") == false) {
String home = findValidPath("user.home", "HOME");
if (home != null) {
sPrefsLocation = home + File.separator + ".android" + File.separator;
}
} else {
String localAppData = findValidPath("LOCALAPPDATA");
if (localAppData == null) {
localAppData = findValidPath("USERPROFILE");
if (localAppData != null) {
localAppData = localAppData + "\\Local Settings\\Application Data";
// check that this directory exists.
File f = new File(localAppData);
if (f.isDirectory() == false) {
localAppData = null;
}
}
// ok if nothing worked, revert to HOME
if (localAppData == null) {
localAppData = findValidPath("HOME", "user.home");
}
}
if (localAppData != null) {
sPrefsLocation = localAppData + "\\Android\\";
}
}
// if all the above failed, try to create a temporary file to get its parent and // if the above failed, we throw an exception.
// use that as the folder if (home == null) {
if (sPrefsLocation == null) {
// no home dir?
throw new AndroidLocationException( throw new AndroidLocationException(
"Unable to get the home directory. Make sure the user.home property is set up"); "Unable to get the home directory. Make sure the user.home property is set up");
} else { } else {
sPrefsLocation = home + File.separator + ".android" + File.separator;
// make sure the folder exists! // make sure the folder exists!
File f = new File(sPrefsLocation); File f = new File(sPrefsLocation);
if (f.exists() == false) { if (f.exists() == false) {
@@ -107,7 +75,7 @@ public final class AndroidLocation {
} }
} }
} }
return sPrefsLocation; return sPrefsLocation;
} }

View File

@@ -3,6 +3,8 @@
<name>adt</name> <name>adt</name>
<comment></comment> <comment></comment>
<projects> <projects>
<project>SdkLib</project>
<project>SdkUiLib</project>
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand> <buildCommand>

View File

@@ -82,9 +82,11 @@ public class Sdk {
logMessages.add(throwable.getMessage()); logMessages.add(throwable.getMessage());
} }
} }
public void warning(String warningFormat, Object... arg) { public void warning(String warningFormat, Object... arg) {
logMessages.add(String.format(warningFormat, arg)); logMessages.add(String.format(warningFormat, arg));
} }
public void printf(String msgFormat, Object... arg) { public void printf(String msgFormat, Object... arg) {
logMessages.add(String.format(msgFormat, arg)); logMessages.add(String.format(msgFormat, arg));
} }

View File

@@ -158,9 +158,6 @@ public class AndroidConstants {
/** Regexp for aidl extension, i.e. "\.aidl$" */ /** Regexp for aidl extension, i.e. "\.aidl$" */
public final static String RE_AIDL_EXT = "\\.aidl$"; //$NON-NLS-1$ public final static String RE_AIDL_EXT = "\\.aidl$"; //$NON-NLS-1$
/** Namespace for the resource XML, i.e. "http://schemas.android.com/apk/res/android" */
public final static String NS_RESOURCES = "http://schemas.android.com/apk/res/android"; //$NON-NLS-1$
/** Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s" */ /** Namespace pattern for the custom resource XML, i.e. "http://schemas.android.com/apk/res/%s" */
public final static String NS_CUSTOM_RESOURCES = "http://schemas.android.com/apk/res/%1$s"; //$NON-NLS-1$ public final static String NS_CUSTOM_RESOURCES = "http://schemas.android.com/apk/res/%1$s"; //$NON-NLS-1$

View File

@@ -18,6 +18,7 @@ package com.android.ide.eclipse.common.project;
import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener; import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarker;
@@ -442,7 +443,7 @@ public class AndroidManifestParser {
* @param attributeName the name of the attribute to look for. * @param attributeName the name of the attribute to look for.
* @param hasNamespace Indicates whether the attribute has an android namespace. * @param hasNamespace Indicates whether the attribute has an android namespace.
* @return a String with the value or null if the attribute was not found. * @return a String with the value or null if the attribute was not found.
* @see AndroidConstants#NS_RESOURCES * @see SdkConstants#NS_RESOURCES
*/ */
private String getAttributeValue(Attributes attributes, String attributeName, private String getAttributeValue(Attributes attributes, String attributeName,
boolean hasNamespace) { boolean hasNamespace) {
@@ -450,7 +451,7 @@ public class AndroidManifestParser {
for (int i = 0 ; i < count ; i++) { for (int i = 0 ; i < count ; i++) {
if (attributeName.equals(attributes.getLocalName(i)) && if (attributeName.equals(attributes.getLocalName(i)) &&
((hasNamespace && ((hasNamespace &&
AndroidConstants.NS_RESOURCES.equals(attributes.getURI(i))) || SdkConstants.NS_RESOURCES.equals(attributes.getURI(i))) ||
(hasNamespace == false && attributes.getURI(i).length() == 0))) { (hasNamespace == false && attributes.getURI(i).length() == 0))) {
return attributes.getValue(i); return attributes.getValue(i);
} }

View File

@@ -16,7 +16,7 @@
package com.android.ide.eclipse.common.project; package com.android.ide.eclipse.common.project;
import com.android.ide.eclipse.common.AndroidConstants; import com.android.sdklib.SdkConstants;
import java.util.Iterator; import java.util.Iterator;
@@ -48,7 +48,7 @@ public class AndroidXPathFactory {
public String getNamespaceURI(String prefix) { public String getNamespaceURI(String prefix) {
if (prefix != null) { if (prefix != null) {
if (prefix.equals(mAndroidPrefix)) { if (prefix.equals(mAndroidPrefix)) {
return AndroidConstants.NS_RESOURCES; return SdkConstants.NS_RESOURCES;
} }
} }

View File

@@ -17,7 +17,6 @@
package com.android.ide.eclipse.editors; package com.android.ide.eclipse.editors;
import com.android.ide.eclipse.adt.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
@@ -29,6 +28,7 @@ import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiFlagAttributeNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
@@ -199,13 +199,13 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
* *
* @param node The current node. Must not be null. * @param node The current node. Must not be null.
* @param nsUri The namespace URI of which the prefix is to be found, * @param nsUri The namespace URI of which the prefix is to be found,
* e.g. AndroidConstants.NS_RESOURCES * e.g. {@link SdkConstants#NS_RESOURCES}
* @return The first prefix declared or the default "android" prefix. * @return The first prefix declared or the default "android" prefix.
*/ */
private String lookupNamespacePrefix(Node node, String nsUri) { private String lookupNamespacePrefix(Node node, String nsUri) {
// Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java // Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java
// The following emulates this: // The following emulates this:
// String prefix = node.lookupPrefix(AndroidConstants.NS_RESOURCES); // String prefix = node.lookupPrefix(SdkConstants.NS_RESOURCES);
if (XmlnsAttributeDescriptor.XMLNS_URI.equals(nsUri)) { if (XmlnsAttributeDescriptor.XMLNS_URI.equals(nsUri)) {
return "xmlns"; //$NON-NLS-1$ return "xmlns"; //$NON-NLS-1$
@@ -223,7 +223,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
Node attr = attrs.item(n); Node attr = attrs.item(n);
if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$ if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$
String uri = attr.getNodeValue(); String uri = attr.getNodeValue();
if (AndroidConstants.NS_RESOURCES.equals(uri)) { if (SdkConstants.NS_RESOURCES.equals(uri)) {
return attr.getLocalName(); return attr.getLocalName();
} }
visited.add(uri); visited.add(uri);
@@ -234,7 +234,7 @@ public abstract class AndroidContentAssist implements IContentAssistProcessor {
// Use a sensible default prefix if we can't find one. // Use a sensible default prefix if we can't find one.
// We need to make sure the prefix is not one that was declared in the scope // We need to make sure the prefix is not one that was declared in the scope
// visited above. // visited above.
prefix = AndroidConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$ prefix = SdkConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$
String base = prefix; String base = prefix;
for (int i = 1; visited.contains(prefix); i++) { for (int i = 1; visited.contains(prefix); i++) {
prefix = base + Integer.toString(i); prefix = base + Integer.toString(i);

View File

@@ -17,10 +17,10 @@
package com.android.ide.eclipse.editors.descriptors; package com.android.ide.eclipse.editors.descriptors;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.IconFactory; import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Image;
@@ -45,7 +45,7 @@ public abstract class AttributeDescriptor {
* *
* @param xmlLocalName The XML name of the attribute (case sensitive) * @param xmlLocalName The XML name of the attribute (case sensitive)
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
*/ */
public AttributeDescriptor(String xmlLocalName, String nsUri) { public AttributeDescriptor(String xmlLocalName, String nsUri) {
mXmlLocalName = xmlLocalName; mXmlLocalName = xmlLocalName;

View File

@@ -23,6 +23,7 @@ import com.android.ide.eclipse.common.resources.DeclareStyleableInfo.AttributeIn
import com.android.ide.eclipse.editors.layout.LayoutConstants; import com.android.ide.eclipse.editors.layout.LayoutConstants;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Image;
@@ -75,7 +76,7 @@ public final class DescriptorsUtils {
* @param xmlName The XML attribute name. * @param xmlName The XML attribute name.
* @param uiName The UI attribute name. * @param uiName The UI attribute name.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip An optional tooltip. * @param tooltip An optional tooltip.
* @return A new {@link TextAttributeDescriptor} (or derived) instance. * @return A new {@link TextAttributeDescriptor} (or derived) instance.
*/ */
@@ -90,7 +91,7 @@ public final class DescriptorsUtils {
* @param elementXmlName Optional XML local name of the element to which attributes are * @param elementXmlName Optional XML local name of the element to which attributes are
* being added. When not null, this is used to filter overrides. * being added. When not null, this is used to filter overrides.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param infos The array of {@link AttributeInfo} to read and append to attributes * @param infos The array of {@link AttributeInfo} to read and append to attributes
* @param requiredAttributes An optional set of attributes to mark as "required" (i.e. append * @param requiredAttributes An optional set of attributes to mark as "required" (i.e. append
* a "*" to their UI name as a hint for the user.) If not null, must contains * a "*" to their UI name as a hint for the user.) If not null, must contains
@@ -125,7 +126,7 @@ public final class DescriptorsUtils {
* being added. When not null, this is used to filter overrides. * being added. When not null, this is used to filter overrides.
* @param info The {@link AttributeInfo} to append to attributes * @param info The {@link AttributeInfo} to append to attributes
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param required True if the attribute is to be marked as "required" (i.e. append * @param required True if the attribute is to be marked as "required" (i.e. append
* a "*" to its UI name as a hint for the user.) * a "*" to its UI name as a hint for the user.)
* @param overrides A map [attribute name => TextAttributeDescriptor creator]. A creator * @param overrides A map [attribute name => TextAttributeDescriptor creator]. A creator

View File

@@ -17,9 +17,9 @@
package com.android.ide.eclipse.editors.descriptors; package com.android.ide.eclipse.editors.descriptors;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.IconFactory; import com.android.ide.eclipse.editors.IconFactory;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Image;
@@ -147,7 +147,7 @@ public class ElementDescriptor {
public final String getNamespace() { public final String getNamespace() {
// For now we hard-code the prefix as being "android" // For now we hard-code the prefix as being "android"
if (mXmlName.startsWith("android:")) { //$NON-NLs-1$ if (mXmlName.startsWith("android:")) { //$NON-NLs-1$
return AndroidConstants.NS_RESOURCES; return SdkConstants.NS_RESOURCES;
} }
return ""; //$NON-NLs-1$ return ""; //$NON-NLs-1$

View File

@@ -16,12 +16,12 @@
package com.android.ide.eclipse.editors.descriptors; package com.android.ide.eclipse.editors.descriptors;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.ResourceType; import com.android.ide.eclipse.common.resources.ResourceType;
import com.android.ide.eclipse.editors.ui.ResourceValueCellEditor; import com.android.ide.eclipse.editors.ui.ResourceValueCellEditor;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiResourceAttributeNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
@@ -39,7 +39,7 @@ public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor
* @param xmlLocalName The XML name of the attribute (case sensitive) * @param xmlLocalName The XML name of the attribute (case sensitive)
* @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null * @param tooltip A non-empty tooltip string or null
*/ */
public ReferenceAttributeDescriptor(String xmlLocalName, String uiName, String nsUri, public ReferenceAttributeDescriptor(String xmlLocalName, String uiName, String nsUri,
@@ -55,7 +55,7 @@ public final class ReferenceAttributeDescriptor extends TextAttributeDescriptor
* @param xmlLocalName The XML name of the attribute (case sensitive) * @param xmlLocalName The XML name of the attribute (case sensitive)
* @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null * @param tooltip A non-empty tooltip string or null
*/ */
public ReferenceAttributeDescriptor(ResourceType resourceType, public ReferenceAttributeDescriptor(ResourceType resourceType,

View File

@@ -16,11 +16,11 @@
package com.android.ide.eclipse.editors.descriptors; package com.android.ide.eclipse.editors.descriptors;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.ui.TextValueCellEditor; import com.android.ide.eclipse.editors.ui.TextValueCellEditor;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProvider;
@@ -47,7 +47,7 @@ public class TextAttributeDescriptor extends AttributeDescriptor implements IPro
* @param xmlLocalName The XML name of the attribute (case sensitive) * @param xmlLocalName The XML name of the attribute (case sensitive)
* @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null * @param tooltip A non-empty tooltip string or null
*/ */
public TextAttributeDescriptor(String xmlLocalName, String uiName, public TextAttributeDescriptor(String xmlLocalName, String uiName,

View File

@@ -19,6 +19,7 @@ package com.android.ide.eclipse.editors.layout;
import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor; import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.layoutlib.api.IXmlPullParser; import com.android.layoutlib.api.IXmlPullParser;
import com.android.sdklib.SdkConstants;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
@@ -61,7 +62,7 @@ public class WidgetPullParser extends BasePullParser {
} }
public String getAttributeNamespace(int index) { public String getAttributeNamespace(int index) {
return AndroidConstants.NS_RESOURCES; return SdkConstants.NS_RESOURCES;
} }
public String getAttributePrefix(int index) { public String getAttributePrefix(int index) {
@@ -78,7 +79,7 @@ public class WidgetPullParser extends BasePullParser {
} }
public String getAttributeValue(String ns, String name) { public String getAttributeValue(String ns, String name) {
if (AndroidConstants.NS_RESOURCES.equals(ns)) { if (SdkConstants.NS_RESOURCES.equals(ns)) {
for (String[] attribute : mAttributes) { for (String[] attribute : mAttributes) {
if (name.equals(attribute[0])) { if (name.equals(attribute[0])) {
return attribute[1]; return attribute[1];

View File

@@ -26,6 +26,7 @@ import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider; import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.sdklib.SdkConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -134,7 +135,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
DescriptorsUtils.appendAttributes(attributes, DescriptorsUtils.appendAttributes(attributes,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
info.getAttributes(), info.getAttributes(),
null, // requiredAttributes null, // requiredAttributes
null /* overrides */); null /* overrides */);
@@ -148,7 +149,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
String.format("Attributes from %1$s", link.getShortClassName()))); String.format("Attributes from %1$s", link.getShortClassName())));
DescriptorsUtils.appendAttributes(attributes, DescriptorsUtils.appendAttributes(attributes,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
attrList, attrList,
null, // requiredAttributes null, // requiredAttributes
null /* overrides */); null /* overrides */);
@@ -163,7 +164,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
boolean need_separator = true; boolean need_separator = true;
for (AttributeInfo attr_info : layoutParams.getAttributes()) { for (AttributeInfo attr_info : layoutParams.getAttributes()) {
if (DescriptorsUtils.containsAttribute(layoutAttributes, if (DescriptorsUtils.containsAttribute(layoutAttributes,
AndroidConstants.NS_RESOURCES, attr_info)) { SdkConstants.NS_RESOURCES, attr_info)) {
continue; continue;
} }
if (need_separator) { if (need_separator) {
@@ -182,7 +183,7 @@ public final class LayoutDescriptors implements IDescriptorProvider {
} }
DescriptorsUtils.appendAttribute(layoutAttributes, DescriptorsUtils.appendAttribute(layoutAttributes,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
attr_info, attr_info,
false, // required false, // required
null /* overrides */); null /* overrides */);

View File

@@ -16,10 +16,10 @@
package com.android.ide.eclipse.editors.layout.parts; package com.android.ide.eclipse.editors.layout.parts;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener; import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Point;
@@ -177,7 +177,7 @@ public abstract class UiElementEditPart extends AbstractGraphicalEditPart
NamedNodeMap nodeAttributes = xmlNode.getAttributes(); NamedNodeMap nodeAttributes = xmlNode.getAttributes();
if (nodeAttributes != null) { if (nodeAttributes != null) {
Node attr = nodeAttributes.getNamedItemNS( Node attr = nodeAttributes.getNamedItemNS(
AndroidConstants.NS_RESOURCES, attrName); SdkConstants.NS_RESOURCES, attrName);
if (attr != null) { if (attr != null) {
return attr.getNodeValue(); return attr.getNodeValue();
} }

View File

@@ -26,6 +26,7 @@ import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
@@ -109,7 +110,7 @@ public class UiViewElementNode extends UiElementNode {
if (need_xmlns) { if (need_xmlns) {
AttributeDescriptor desc = new XmlnsAttributeDescriptor( AttributeDescriptor desc = new XmlnsAttributeDescriptor(
"android", //$NON-NLS-1$ "android", //$NON-NLS-1$
AndroidConstants.NS_RESOURCES); SdkConstants.NS_RESOURCES);
mCachedAttributeDescriptors[direct_attrs.length + layout_attrs.length] = desc; mCachedAttributeDescriptors[direct_attrs.length + layout_attrs.length] = desc;
} }

View File

@@ -28,6 +28,7 @@ import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
@@ -166,7 +167,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
"android", //$NON-NLS-1$ "android", //$NON-NLS-1$
AndroidConstants.NS_RESOURCES); SdkConstants.NS_RESOURCES);
// -- setup the required attributes overrides -- // -- setup the required attributes overrides --
@@ -355,7 +356,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
ArrayList<AttributeDescriptor> attrDescs = new ArrayList<AttributeDescriptor>(); ArrayList<AttributeDescriptor> attrDescs = new ArrayList<AttributeDescriptor>();
DescriptorsUtils.appendAttributes(attrDescs, DescriptorsUtils.appendAttributes(attrDescs,
elemDesc.getXmlLocalName(), elemDesc.getXmlLocalName(),
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
style.getAttributes(), style.getAttributes(),
requiredAttributes, requiredAttributes,
overrides); overrides);

View File

@@ -44,7 +44,7 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
* @param xmlLocalName The XML name of the attribute (case sensitive, with android: prefix). * @param xmlLocalName The XML name of the attribute (case sensitive, with android: prefix).
* @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null. * @param tooltip A non-empty tooltip string or null.
* @param mandatory indicates if the class attribute is mandatory. * @param mandatory indicates if the class attribute is mandatory.
*/ */
@@ -64,7 +64,7 @@ public class ClassAttributeDescriptor extends TextAttributeDescriptor {
* @param xmlLocalName The XML local name of the attribute (case sensitive). * @param xmlLocalName The XML local name of the attribute (case sensitive).
* @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null. * @param uiName The UI name of the attribute. Cannot be an empty string and cannot be null.
* @param nsUri The URI of the attribute. Can be null if attribute has no namespace. * @param nsUri The URI of the attribute. Can be null if attribute has no namespace.
* See {@link AndroidConstants#NS_RESOURCES} for a common value. * See {@link SdkConstants#NS_RESOURCES} for a common value.
* @param tooltip A non-empty tooltip string or null. * @param tooltip A non-empty tooltip string or null.
* @param mandatory indicates if the class attribute is mandatory. * @param mandatory indicates if the class attribute is mandatory.
*/ */

View File

@@ -16,12 +16,12 @@
package com.android.ide.eclipse.editors.manifest.model; package com.android.ide.eclipse.editors.manifest.model;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.editors.manifest.descriptors.ManifestElementDescriptor; import com.android.ide.eclipse.editors.manifest.descriptors.ManifestElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@@ -74,10 +74,10 @@ public final class UiManifestElementNode extends UiElementNode {
if (desc != manifestDescriptors.getManifestElement() && if (desc != manifestDescriptors.getManifestElement() &&
desc != manifestDescriptors.getApplicationElement()) { desc != manifestDescriptors.getApplicationElement()) {
Element elem = (Element) getXmlNode(); Element elem = (Element) getXmlNode();
String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, String attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_NAME_ATTR); AndroidManifestDescriptors.ANDROID_NAME_ATTR);
if (attr == null || attr.length() == 0) { if (attr == null || attr.length() == 0) {
attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_LABEL_ATTR); AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
} }
if (attr != null && attr.length() > 0) { if (attr != null && attr.length() > 0) {

View File

@@ -16,13 +16,13 @@
package com.android.ide.eclipse.editors.menu.descriptors; package com.android.ide.eclipse.editors.menu.descriptors;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.resources.DeclareStyleableInfo; import com.android.ide.eclipse.common.resources.DeclareStyleableInfo;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider; import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.sdklib.SdkConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
@@ -121,7 +121,7 @@ public final class MenuDescriptors implements IDescriptorProvider {
false /* mandatory */); false /* mandatory */);
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor("android", //$NON-NLS-1$ XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor("android", //$NON-NLS-1$
AndroidConstants.NS_RESOURCES); SdkConstants.NS_RESOURCES);
updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$ updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$
mDescriptor.setChildren(new ElementDescriptor[] { top_item, top_group }); mDescriptor.setChildren(new ElementDescriptor[] { top_item, top_group });
@@ -159,7 +159,7 @@ public final class MenuDescriptors implements IDescriptorProvider {
if (style != null) { if (style != null) {
DescriptorsUtils.appendAttributes(descs, DescriptorsUtils.appendAttributes(descs,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
style.getAttributes(), style.getAttributes(),
null, // requiredAttributes null, // requiredAttributes
null); // overrides null); // overrides

View File

@@ -18,7 +18,6 @@ package com.android.ide.eclipse.editors.uimodel;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor; import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
@@ -31,6 +30,7 @@ import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescr
import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors; import com.android.ide.eclipse.editors.resources.descriptors.ResourcesDescriptors;
import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState; import com.android.ide.eclipse.editors.uimodel.IUiUpdateListener.UiUpdateState;
import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors; import com.android.ide.eclipse.editors.xml.descriptors.XmlDescriptors;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorInput;
@@ -201,21 +201,21 @@ public class UiElementNode implements IPropertySource {
// just using the UI name below. // just using the UI name below.
Element elem = (Element) mXmlNode; Element elem = (Element) mXmlNode;
String attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, String attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_NAME_ATTR); AndroidManifestDescriptors.ANDROID_NAME_ATTR);
if (attr == null || attr.length() == 0) { if (attr == null || attr.length() == 0) {
attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
AndroidManifestDescriptors.ANDROID_LABEL_ATTR); AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
} }
if (attr == null || attr.length() == 0) { if (attr == null || attr.length() == 0) {
attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
XmlDescriptors.PREF_KEY_ATTR); XmlDescriptors.PREF_KEY_ATTR);
} }
if (attr == null || attr.length() == 0) { if (attr == null || attr.length() == 0) {
attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR); attr = elem.getAttribute(ResourcesDescriptors.NAME_ATTR);
} }
if (attr == null || attr.length() == 0) { if (attr == null || attr.length() == 0) {
attr = elem.getAttributeNS(AndroidConstants.NS_RESOURCES, attr = elem.getAttributeNS(SdkConstants.NS_RESOURCES,
LayoutDescriptors.ID_ATTR); LayoutDescriptors.ID_ATTR);
if (attr != null && attr.length() > 0) { if (attr != null && attr.length() > 0) {
@@ -1205,13 +1205,13 @@ public class UiElementNode implements IPropertySource {
* *
* @param node The current node. Must not be null. * @param node The current node. Must not be null.
* @param nsUri The namespace URI of which the prefix is to be found, * @param nsUri The namespace URI of which the prefix is to be found,
* e.g. AndroidConstants.NS_RESOURCES * e.g. SdkConstants.NS_RESOURCES
* @return The first prefix declared or the default "android" prefix. * @return The first prefix declared or the default "android" prefix.
*/ */
private String lookupNamespacePrefix(Node node, String nsUri) { private String lookupNamespacePrefix(Node node, String nsUri) {
// Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java // Note: Node.lookupPrefix is not implemented in wst/xml/core NodeImpl.java
// The following code emulates this simple call: // The following code emulates this simple call:
// String prefix = node.lookupPrefix(AndroidConstants.NS_RESOURCES); // String prefix = node.lookupPrefix(SdkConstants.NS_RESOURCES);
// if the requested URI is null, it denotes an attribute with no namespace. // if the requested URI is null, it denotes an attribute with no namespace.
if (nsUri == null) { if (nsUri == null) {
@@ -1234,7 +1234,7 @@ public class UiElementNode implements IPropertySource {
if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$ if ("xmlns".equals(attr.getPrefix())) { //$NON-NLS-1$
String uri = attr.getNodeValue(); String uri = attr.getNodeValue();
String nsPrefix = attr.getLocalName(); String nsPrefix = attr.getLocalName();
if (AndroidConstants.NS_RESOURCES.equals(uri)) { if (SdkConstants.NS_RESOURCES.equals(uri)) {
return nsPrefix; return nsPrefix;
} }
visited.add(nsPrefix); visited.add(nsPrefix);
@@ -1245,7 +1245,7 @@ public class UiElementNode implements IPropertySource {
// Use a sensible default prefix if we can't find one. // Use a sensible default prefix if we can't find one.
// We need to make sure the prefix is not one that was declared in the scope // We need to make sure the prefix is not one that was declared in the scope
// visited above. // visited above.
String prefix = AndroidConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$ String prefix = SdkConstants.NS_RESOURCES.equals(nsUri) ? "android" : "ns"; //$NON-NLS-1$ //$NON-NLS-2$
String base = prefix; String base = prefix;
for (int i = 1; visited.contains(prefix); i++) { for (int i = 1; visited.contains(prefix); i++) {
prefix = base + Integer.toString(i); prefix = base + Integer.toString(i);

View File

@@ -18,7 +18,6 @@ package com.android.ide.eclipse.editors.uimodel;
import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.sdk.AndroidTargetData;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.AndroidEditor; import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils; import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
@@ -26,6 +25,7 @@ import com.android.ide.eclipse.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.ui.SectionHelper; import com.android.ide.eclipse.editors.ui.SectionHelper;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
@@ -135,7 +135,7 @@ public class UiListAttributeNode extends UiAbstractTextAttributeNode {
// FrameworkResourceManager expects a specific prefix for the attribute. // FrameworkResourceManager expects a specific prefix for the attribute.
String prefix = ""; String prefix = "";
if (AndroidConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) { if (SdkConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) {
prefix = "android:"; //$NON-NLS-1$ prefix = "android:"; //$NON-NLS-1$
} else if (XmlnsAttributeDescriptor.XMLNS_URI.equals(descriptor.getNamespaceUri())) { } else if (XmlnsAttributeDescriptor.XMLNS_URI.equals(descriptor.getNamespaceUri())) {
prefix = "xmlns:"; //$NON-NLS-1$ prefix = "xmlns:"; //$NON-NLS-1$

View File

@@ -163,7 +163,7 @@ class NewXmlFileCreationPage extends WizardPage {
/** /**
* If the generated resource XML file requires an "android" XMLNS, this should be set * If the generated resource XML file requires an "android" XMLNS, this should be set
* to {@link AndroidConstants#NS_RESOURCES}. When it is null, no XMLNS is generated. * to {@link SdkConstants#NS_RESOURCES}. When it is null, no XMLNS is generated.
*/ */
String getXmlns() { String getXmlns() {
return mXmlns; return mXmlns;
@@ -188,7 +188,7 @@ class NewXmlFileCreationPage extends WizardPage {
ResourceFolderType.LAYOUT, // folder type ResourceFolderType.LAYOUT, // folder type
AndroidTargetData.DESCRIPTOR_LAYOUT, // root seed AndroidTargetData.DESCRIPTOR_LAYOUT, // root seed
"LinearLayout", // default root "LinearLayout", // default root
AndroidConstants.NS_RESOURCES, // xmlns SdkConstants.NS_RESOURCES, // xmlns
"android:layout_width=\"wrap_content\"\n" + // default attributes "android:layout_width=\"wrap_content\"\n" + // default attributes
"android:layout_height=\"wrap_content\"" "android:layout_height=\"wrap_content\""
), ),
@@ -205,7 +205,7 @@ class NewXmlFileCreationPage extends WizardPage {
ResourceFolderType.MENU, // folder type ResourceFolderType.MENU, // folder type
MenuDescriptors.MENU_ROOT_ELEMENT, // root seed MenuDescriptors.MENU_ROOT_ELEMENT, // root seed
null, // default root null, // default root
AndroidConstants.NS_RESOURCES, // xmlns SdkConstants.NS_RESOURCES, // xmlns
null // default attributes null // default attributes
), ),
new TypeInfo("Preference", // UI name new TypeInfo("Preference", // UI name
@@ -213,7 +213,7 @@ class NewXmlFileCreationPage extends WizardPage {
ResourceFolderType.XML, // folder type ResourceFolderType.XML, // folder type
AndroidTargetData.DESCRIPTOR_PREFERENCES, // root seed AndroidTargetData.DESCRIPTOR_PREFERENCES, // root seed
AndroidConstants.CLASS_PREFERENCE_SCREEN, // default root AndroidConstants.CLASS_PREFERENCE_SCREEN, // default root
AndroidConstants.NS_RESOURCES, // xmlns SdkConstants.NS_RESOURCES, // xmlns
null // default attributes null // default attributes
), ),
new TypeInfo("Searchable", // UI name new TypeInfo("Searchable", // UI name
@@ -221,7 +221,7 @@ class NewXmlFileCreationPage extends WizardPage {
ResourceFolderType.XML, // folder type ResourceFolderType.XML, // folder type
AndroidTargetData.DESCRIPTOR_SEARCHABLE, // root seed AndroidTargetData.DESCRIPTOR_SEARCHABLE, // root seed
null, // default root null, // default root
AndroidConstants.NS_RESOURCES, // xmlns SdkConstants.NS_RESOURCES, // xmlns
null // default attributes null // default attributes
), ),
new TypeInfo("Animation", // UI name new TypeInfo("Animation", // UI name

View File

@@ -26,6 +26,7 @@ import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiDocumentNode; import com.android.ide.eclipse.editors.uimodel.UiDocumentNode;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProject;
@@ -80,7 +81,7 @@ public class XmlEditor extends AndroidEditor {
FirstElementParser.Result result = FirstElementParser.parse( FirstElementParser.Result result = FirstElementParser.parse(
file.getLocation().toOSString(), file.getLocation().toOSString(),
AndroidConstants.NS_RESOURCES); SdkConstants.NS_RESOURCES);
if (result != null) { if (result != null) {
String name = result.getElement(); String name = result.getElement();

View File

@@ -25,9 +25,10 @@ import com.android.ide.eclipse.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor; import com.android.ide.eclipse.editors.descriptors.DocumentDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider; import com.android.ide.eclipse.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor; import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.sdklib.SdkConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Map; import java.util.Map;
@@ -111,7 +112,7 @@ public final class XmlDescriptors implements IDescriptorProvider {
XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(
"android", //$NON-NLS-1$ "android", //$NON-NLS-1$
AndroidConstants.NS_RESOURCES); SdkConstants.NS_RESOURCES);
ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns); ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns);
ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns); ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns);
@@ -191,7 +192,7 @@ public final class XmlDescriptors implements IDescriptorProvider {
if (style != null) { if (style != null) {
DescriptorsUtils.appendAttributes(descs, DescriptorsUtils.appendAttributes(descs,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
style.getAttributes(), style.getAttributes(),
null, // requiredAttributes null, // requiredAttributes
null); // overrides null); // overrides
@@ -280,7 +281,7 @@ public final class XmlDescriptors implements IDescriptorProvider {
ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>(); ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
DescriptorsUtils.appendAttributes(attributes, DescriptorsUtils.appendAttributes(attributes,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
info.getAttributes(), info.getAttributes(),
null, // requiredAttributes null, // requiredAttributes
null); // overrides null); // overrides
@@ -294,7 +295,7 @@ public final class XmlDescriptors implements IDescriptorProvider {
String.format("Attributes from %1$s", link.getShortClassName()))); String.format("Attributes from %1$s", link.getShortClassName())));
DescriptorsUtils.appendAttributes(attributes, DescriptorsUtils.appendAttributes(attributes,
null, // elementName null, // elementName
AndroidConstants.NS_RESOURCES, SdkConstants.NS_RESOURCES,
attrList, attrList,
null, // requiredAttributes null, // requiredAttributes
null); // overrides null); // overrides

View File

@@ -5,5 +5,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="lib" path="kxml2-2.3.0.jar"/> <classpathentry kind="lib" path="kxml2-2.3.0.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -3,6 +3,7 @@
<name>adt-tests</name> <name>adt-tests</name>
<comment></comment> <comment></comment>
<projects> <projects>
<project>SdkLib</project>
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand> <buildCommand>

View File

@@ -16,18 +16,17 @@
package com.android.ide.eclipse.editors.layout; package com.android.ide.eclipse.editors.layout;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor; import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.editors.mock.MockXmlNode; import com.android.ide.eclipse.editors.mock.MockXmlNode;
import com.android.ide.eclipse.editors.uimodel.UiElementNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode;
import com.android.sdklib.SdkConstants;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import junit.framework.TestCase; import junit.framework.TestCase;
@@ -47,22 +46,22 @@ public class UiElementPullParserTest extends TestCase {
// Also add some dummy attributes. // Also add some dummy attributes.
ElementDescriptor buttonDescriptor = new ElementDescriptor("Button", "Button", "", "", ElementDescriptor buttonDescriptor = new ElementDescriptor("Button", "Button", "", "",
new AttributeDescriptor[] { new AttributeDescriptor[] {
new TextAttributeDescriptor("name", "name", AndroidConstants.NS_RESOURCES, ""), new TextAttributeDescriptor("name", "name", SdkConstants.NS_RESOURCES, ""),
new TextAttributeDescriptor("text", "text", AndroidConstants.NS_RESOURCES, ""), new TextAttributeDescriptor("text", "text", SdkConstants.NS_RESOURCES, ""),
}, },
new ElementDescriptor[] {}, false); new ElementDescriptor[] {}, false);
ElementDescriptor textDescriptor = new ElementDescriptor("TextView", "TextView", "", "", ElementDescriptor textDescriptor = new ElementDescriptor("TextView", "TextView", "", "",
new AttributeDescriptor[] { new AttributeDescriptor[] {
new TextAttributeDescriptor("name", "name", AndroidConstants.NS_RESOURCES, ""), new TextAttributeDescriptor("name", "name", SdkConstants.NS_RESOURCES, ""),
new TextAttributeDescriptor("text", "text", AndroidConstants.NS_RESOURCES, ""), }, new TextAttributeDescriptor("text", "text", SdkConstants.NS_RESOURCES, ""), },
new ElementDescriptor[] {}, false); new ElementDescriptor[] {}, false);
ElementDescriptor linearDescriptor = new ElementDescriptor("LinearLayout", "Linear Layout", ElementDescriptor linearDescriptor = new ElementDescriptor("LinearLayout", "Linear Layout",
"", "", "", "",
new AttributeDescriptor[] { new AttributeDescriptor[] {
new TextAttributeDescriptor("orientation", "orientation", new TextAttributeDescriptor("orientation", "orientation",
AndroidConstants.NS_RESOURCES, ""), SdkConstants.NS_RESOURCES, ""),
}, },
new ElementDescriptor[] { }, false); new ElementDescriptor[] { }, false);
@@ -70,7 +69,7 @@ public class UiElementPullParserTest extends TestCase {
"Relative Layout", "", "", "Relative Layout", "", "",
new AttributeDescriptor[] { new AttributeDescriptor[] {
new TextAttributeDescriptor("orientation", "orientation", new TextAttributeDescriptor("orientation", "orientation",
AndroidConstants.NS_RESOURCES, ""), SdkConstants.NS_RESOURCES, ""),
}, },
new ElementDescriptor[] { }, false); new ElementDescriptor[] { }, false);
@@ -99,8 +98,8 @@ public class UiElementPullParserTest extends TestCase {
*/ */
MockXmlNode button1 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE, MockXmlNode button1 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE,
null); null);
button1.addAttributes(AndroidConstants.NS_RESOURCES, "name", "button1"); button1.addAttributes(SdkConstants.NS_RESOURCES, "name", "button1");
button1.addAttributes(AndroidConstants.NS_RESOURCES, "text", "button1text"); button1.addAttributes(SdkConstants.NS_RESOURCES, "text", "button1text");
// create a map of the attributes we add to the multi-attribute nodes so that // create a map of the attributes we add to the multi-attribute nodes so that
// we can more easily test the values when we parse the XML. // we can more easily test the values when we parse the XML.
@@ -112,8 +111,8 @@ public class UiElementPullParserTest extends TestCase {
MockXmlNode button2 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE, MockXmlNode button2 = new MockXmlNode(null /* namespace */, "Button", Node.ELEMENT_NODE,
null); null);
button2.addAttributes(AndroidConstants.NS_RESOURCES, "name", "button2"); button2.addAttributes(SdkConstants.NS_RESOURCES, "name", "button2");
button2.addAttributes(AndroidConstants.NS_RESOURCES, "text", "button2text"); button2.addAttributes(SdkConstants.NS_RESOURCES, "text", "button2text");
button2Map = new HashMap<String, String>(); button2Map = new HashMap<String, String>();
button2Map.put("name", "button2"); button2Map.put("name", "button2");
@@ -121,8 +120,8 @@ public class UiElementPullParserTest extends TestCase {
MockXmlNode text = new MockXmlNode(null /* namespace */, "TextView", Node.ELEMENT_NODE, MockXmlNode text = new MockXmlNode(null /* namespace */, "TextView", Node.ELEMENT_NODE,
null); null);
text.addAttributes(AndroidConstants.NS_RESOURCES, "name", "text1"); text.addAttributes(SdkConstants.NS_RESOURCES, "name", "text1");
text.addAttributes(AndroidConstants.NS_RESOURCES, "text", "text1text"); text.addAttributes(SdkConstants.NS_RESOURCES, "text", "text1text");
textMap = new HashMap<String, String>(); textMap = new HashMap<String, String>();
textMap.put("name", "text1"); textMap.put("name", "text1");
@@ -130,17 +129,17 @@ public class UiElementPullParserTest extends TestCase {
MockXmlNode relative = new MockXmlNode(null /* namespace */, "RelativeLayout", MockXmlNode relative = new MockXmlNode(null /* namespace */, "RelativeLayout",
Node.ELEMENT_NODE, new MockXmlNode[] { button2, text }); Node.ELEMENT_NODE, new MockXmlNode[] { button2, text });
relative.addAttributes(AndroidConstants.NS_RESOURCES, "orientation", "toto"); relative.addAttributes(SdkConstants.NS_RESOURCES, "orientation", "toto");
MockXmlNode linear = new MockXmlNode(null /* namespace */, "LinearLayout", MockXmlNode linear = new MockXmlNode(null /* namespace */, "LinearLayout",
Node.ELEMENT_NODE, new MockXmlNode[] { button1, relative }); Node.ELEMENT_NODE, new MockXmlNode[] { button1, relative });
linear.addAttributes(AndroidConstants.NS_RESOURCES, "orientation", "vertical"); linear.addAttributes(SdkConstants.NS_RESOURCES, "orientation", "vertical");
MockXmlNode root = new MockXmlNode(null /* namespace */, "root", Node.ELEMENT_NODE, MockXmlNode root = new MockXmlNode(null /* namespace */, "root", Node.ELEMENT_NODE,
new MockXmlNode[] { linear }); new MockXmlNode[] { linear });
// put the namespace/prefix in place // put the namespace/prefix in place
root.setPrefix(AndroidConstants.NS_RESOURCES, "android"); root.setPrefix(SdkConstants.NS_RESOURCES, "android");
// load the xml into the UiElementNode // load the xml into the UiElementNode
ui.loadFromXmlNode(root); ui.loadFromXmlNode(root);
@@ -165,7 +164,7 @@ public class UiElementPullParserTest extends TestCase {
assertEquals("LinearLayout", parser.getName()); assertEquals("LinearLayout", parser.getName());
assertEquals(1, parser.getAttributeCount()); assertEquals(1, parser.getAttributeCount());
assertEquals("orientation", parser.getAttributeName(0)); assertEquals("orientation", parser.getAttributeName(0));
assertEquals(AndroidConstants.NS_RESOURCES, parser.getAttributeNamespace(0)); assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(0));
assertEquals("android", parser.getAttributePrefix(0)); assertEquals("android", parser.getAttributePrefix(0));
assertEquals("vertical", parser.getAttributeValue(0)); assertEquals("vertical", parser.getAttributeValue(0));
@@ -183,7 +182,7 @@ public class UiElementPullParserTest extends TestCase {
assertEquals("RelativeLayout", parser.getName()); assertEquals("RelativeLayout", parser.getName());
assertEquals(1, parser.getAttributeCount()); assertEquals(1, parser.getAttributeCount());
assertEquals("orientation", parser.getAttributeName(0)); assertEquals("orientation", parser.getAttributeName(0));
assertEquals(AndroidConstants.NS_RESOURCES, parser.getAttributeNamespace(0)); assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(0));
assertEquals("android", parser.getAttributePrefix(0)); assertEquals("android", parser.getAttributePrefix(0));
assertEquals("toto", parser.getAttributeValue(0)); assertEquals("toto", parser.getAttributeValue(0));
@@ -234,7 +233,7 @@ public class UiElementPullParserTest extends TestCase {
assertNotNull(referenceValue); assertNotNull(referenceValue);
assertEquals(referenceValue, value); assertEquals(referenceValue, value);
assertEquals(AndroidConstants.NS_RESOURCES, parser.getAttributeNamespace(i)); assertEquals(SdkConstants.NS_RESOURCES, parser.getAttributeNamespace(i));
assertEquals("android", parser.getAttributePrefix(i)); assertEquals("android", parser.getAttributePrefix(i));
} }

View File

@@ -114,7 +114,7 @@ knownTests=(
# system-wide tests # system-wide tests
"framework frameworks/base/tests/FrameworkTest # com.android.frameworktest.AllTests com.android.frameworktest.tests #" "framework frameworks/base/tests/FrameworkTest # com.android.frameworktest.AllTests com.android.frameworktest.tests #"
"android frameworks/base/tests/AndroidTests com.android.unit_tests AndroidTests # #" "android frameworks/base/tests/AndroidTests com.android.unit_tests AndroidTests # #"
"smoke tests/SmokeTest com.android.smoketest # com.android.smoketest.tests #" "smoke frameworks/base/tests/SmokeTest com.android.smoketest # com.android.smoketest.tests #"
"core frameworks/base/tests/CoreTests # android.core.CoreTests android.core #" "core frameworks/base/tests/CoreTests # android.core.CoreTests android.core #"
"libcore frameworks/base/tests/CoreTests # android.core.JavaTests android.core #" "libcore frameworks/base/tests/CoreTests # android.core.JavaTests android.core #"
"apidemos samples/ApiDemos com.example.android.apis # com.example.android.apis.tests #" "apidemos samples/ApiDemos com.example.android.apis # com.example.android.apis.tests #"

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<project name="ACTIVITY_NAME" default="package"> <project name="PROJECT_NAME" default="package">
<!-- The build.properties file can be created by you and is never touched <!-- The build.properties file can be created by you and is never touched
by activitycreator. If you want to manually set properties, this is by activitycreator. If you want to manually set properties, this is

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<project name="ACTIVITY_NAME" default="help"> <project name="PROJECT_NAME" default="help">
<!-- The local.properties file is created and updated by the 'android' tool. <!-- The local.properties file is created and updated by the 'android' tool.
It contain the path to the SDK. It should *NOT* be checked in in Version It contain the path to the SDK. It should *NOT* be checked in in Version

View File

@@ -45,6 +45,8 @@ public class CommandLineProcessor {
public static final String KEY_HELP = "help"; public static final String KEY_HELP = "help";
/** The global verbose flag. */ /** The global verbose flag. */
public static final String KEY_VERBOSE = "verbose"; public static final String KEY_VERBOSE = "verbose";
/** The global silent flag. */
public static final String KEY_SILENT = "silent";
/** The internal action flag. */ /** The internal action flag. */
public static final String KEY_ACTION = "action"; public static final String KEY_ACTION = "action";
@@ -65,10 +67,18 @@ public class CommandLineProcessor {
mLog = logger; mLog = logger;
mActions = actions; mActions = actions;
define(MODE.STRING, false, INTERNAL_FLAG, null, KEY_ACTION, "Selected Action", null); define(MODE.STRING, false, INTERNAL_FLAG, null, KEY_ACTION,
"Selected Action", null);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE, "Verbose mode", false); define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE,
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "h", KEY_HELP, "This help", false); "Verbose mode: errors, warnings and informational messages are printed.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "s", KEY_SILENT,
"Silent mode: only errors are printed out.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "h", KEY_HELP,
"This help.",
false);
} }
//------------------ //------------------
@@ -79,6 +89,11 @@ public class CommandLineProcessor {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue(); return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue();
} }
/** Helper that returns true if --silent was requested. */
public boolean isSilent() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_SILENT)).booleanValue();
}
/** Helper that returns true if --help was requested. */ /** Helper that returns true if --help was requested. */
public boolean isHelpRequested() { public boolean isHelpRequested() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_HELP)).booleanValue(); return ((Boolean) getValue(GLOBAL_FLAG, KEY_HELP)).booleanValue();
@@ -204,18 +219,29 @@ public class CommandLineProcessor {
needsHelp = "Missing action name."; needsHelp = "Missing action name.";
} else { } else {
// Validate that all mandatory arguments are non-null for this action // Validate that all mandatory arguments are non-null for this action
String missing = null;
boolean plural = false;
for (Entry<String, Arg> entry : mArguments.entrySet()) { for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue(); Arg arg = entry.getValue();
if (arg.getAction().equals(action)) { if (arg.getAction().equals(action)) {
if (arg.isMandatory() && arg.getCurrentValue() == null) { if (arg.isMandatory() && arg.getCurrentValue() == null) {
needsHelp = String.format("The parameter --%1$s must be defined for action '%2$s'", if (missing == null) {
arg.getLongArg(), missing = "--" + arg.getLongArg();
action); } else {
break; missing += ", --" + arg.getLongArg();
plural = true;
}
} }
} }
} }
if (missing != null) {
needsHelp = String.format("The %1$s %2$s must be defined for action '%3$s'",
plural ? "parameters" : "parameter",
missing,
action);
}
setValue(INTERNAL_FLAG, KEY_ACTION, action); setValue(INTERNAL_FLAG, KEY_ACTION, action);
} }
} }
@@ -324,24 +350,29 @@ public class CommandLineProcessor {
Arg arg = entry.getValue(); Arg arg = entry.getValue();
if (arg.getAction().equals(action)) { if (arg.getAction().equals(action)) {
String value = null; String value = "";
if (arg.getDefaultValue() instanceof String[]) { if (arg.getDefaultValue() instanceof String[]) {
value = "";
for (String v : (String[]) arg.getDefaultValue()) { for (String v : (String[]) arg.getDefaultValue()) {
if (value.length() > 0) { if (value.length() > 0) {
value += "|"; value += ", ";
} }
value += v; value += v;
} }
} else if (arg.getDefaultValue() != null) { } else if (arg.getDefaultValue() != null) {
value = arg.getDefaultValue().toString(); value = arg.getDefaultValue().toString();
} }
if (value.length() > 0) {
value = " (" + value + ")";
}
String required = arg.isMandatory() ? " [required]" : "";
stdout(" -%1$s %2$-10s %3$s%4$s", stdout(" -%1$s %2$-10s %3$s%4$s%5$s",
arg.getShortArg(), arg.getShortArg(),
"--" + arg.getLongArg(), "--" + arg.getLongArg(),
arg.getDescription(), arg.getDescription(),
value == null ? "" : " (" + value + ")"); value,
required);
numOptions++; numOptions++;
} }
} }

View File

@@ -144,7 +144,7 @@ class Main {
if (mSdkFolder == null) { if (mSdkFolder == null) {
errorAndExit("The tools directory property is not set, please make sure you are executing %1$s", errorAndExit("The tools directory property is not set, please make sure you are executing %1$s",
SdkConstants.AndroidCmdName()); SdkConstants.androidCmdName());
} }
// We might get passed a property for the working directory // We might get passed a property for the working directory
@@ -203,19 +203,48 @@ class Main {
IAndroidTarget[] targets = mSdkManager.getTargets(); IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) { if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.", errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
SdkConstants.AndroidCmdName()); SdkConstants.androidCmdName());
} }
IAndroidTarget target = targets[targetId - 1]; IAndroidTarget target = targets[targetId - 1];
ProjectCreator creator = new ProjectCreator(mSdkFolder, ProjectCreator creator = new ProjectCreator(mSdkFolder,
mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE : OutputLevel.NORMAL, mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE :
mSdkCommandLine.isSilent() ? OutputLevel.SILENT :
OutputLevel.NORMAL,
mSdkLog); mSdkLog);
String projectDir = getProjectLocation(mSdkCommandLine.getNewProjectLocation()); String projectDir = getProjectLocation(mSdkCommandLine.getNewProjectLocation());
creator.createProject(projectDir, creator.createProject(projectDir,
mSdkCommandLine.getNewProjectName(), mSdkCommandLine.getNewProjectPackage(), mSdkCommandLine.getNewProjectName(),
mSdkCommandLine.getNewProjectActivity(), target, false /* isTestProject*/); mSdkCommandLine.getNewProjectPackage(),
mSdkCommandLine.getNewProjectActivity(),
target,
false /* isTestProject*/);
} else if (SdkCommandLine.ACTION_UPDATE_PROJECT.equals(action)) {
// get the target and try to resolve it.
IAndroidTarget target = null;
int targetId = mSdkCommandLine.getUpdateProjectTargetId();
if (targetId >= 0) {
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
SdkConstants.androidCmdName());
}
target = targets[targetId - 1];
}
ProjectCreator creator = new ProjectCreator(mSdkFolder,
mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE :
mSdkCommandLine.isSilent() ? OutputLevel.SILENT :
OutputLevel.NORMAL,
mSdkLog);
String projectDir = getProjectLocation(mSdkCommandLine.getUpdateProjectLocation());
creator.updateProject(projectDir,
target,
mSdkCommandLine.getUpdateProjectName());
} else { } else {
mSdkCommandLine.printHelpAndExit(null); mSdkCommandLine.printHelpAndExit(null);
} }
@@ -355,7 +384,7 @@ class Main {
target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based
} else { } else {
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.", errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
SdkConstants.AndroidCmdName()); SdkConstants.androidCmdName());
} }
try { try {
@@ -384,8 +413,7 @@ class Main {
mSdkCommandLine.getNewVmName(), mSdkCommandLine.getNewVmName(),
target, target,
mSdkCommandLine.getNewVmSkin(), mSdkCommandLine.getNewVmSkin(),
null /*sdcardPath*/, mSdkCommandLine.getNewVmSdCard(),
0 /*sdcardSize*/,
hardwareConfig, hardwareConfig,
mSdkLog); mSdkLog);
} }

View File

@@ -31,7 +31,6 @@ public class SdkCommandLine extends CommandLineProcessor {
public static final String ARG_TARGET = "target"; public static final String ARG_TARGET = "target";
public static final String ARG_ALL = "all"; public static final String ARG_ALL = "all";
public static final String KEY_IN = "in";
public static final String KEY_ACTIVITY = ARG_ACTIVITY; public static final String KEY_ACTIVITY = ARG_ACTIVITY;
public static final String KEY_PACKAGE = "package"; public static final String KEY_PACKAGE = "package";
public static final String KEY_MODE = "mode"; public static final String KEY_MODE = "mode";
@@ -40,7 +39,7 @@ public class SdkCommandLine extends CommandLineProcessor {
public static final String KEY_OUT = "out"; public static final String KEY_OUT = "out";
public static final String KEY_FILTER = "filter"; public static final String KEY_FILTER = "filter";
public static final String KEY_SKIN = "skin"; public static final String KEY_SKIN = "skin";
public static final String KEY_SDCARD_PATH = "sdcard"; public static final String KEY_SDCARD = "sdcard";
public final static String ACTION_LIST = "list"; public final static String ACTION_LIST = "list";
public final static String ACTION_NEW_VM = ARG_VM; public final static String ACTION_NEW_VM = ARG_VM;
@@ -72,26 +71,28 @@ public class SdkCommandLine extends CommandLineProcessor {
"Target id of the new VM", null); "Target id of the new VM", null);
define(MODE.STRING, true, ACTION_NEW_VM, "s", KEY_SKIN, define(MODE.STRING, true, ACTION_NEW_VM, "s", KEY_SKIN,
"Skin of the new VM", null); "Skin of the new VM", null);
define(MODE.STRING, true, ACTION_NEW_VM, "p", KEY_SDCARD_PATH, define(MODE.STRING, false, ACTION_NEW_VM, "c", KEY_SDCARD,
"Path to a shared SD card image for the new VM", null); "Path to a shared SD card image, or size of a new sdcard for the new VM", null);
define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE, define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE,
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS }); "Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
define(MODE.STRING, false, ACTION_NEW_PROJECT, "o", KEY_OUT, define(MODE.STRING, true, ACTION_NEW_PROJECT, "o", KEY_OUT,
"Location path of new project", null); "Location path of new project", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "n", KEY_NAME,
"Name of the new project", null);
define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID, define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID,
"Target id of the new project", null); "Target id of the new project", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE, define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE,
"Package name", null); "Package name", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY, define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY,
"Activity name", null); "Activity name", null);
define(MODE.STRING, false, ACTION_NEW_PROJECT, "n", KEY_NAME,
"Project name", null);
define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "i", KEY_IN, define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "o", KEY_OUT,
"Directory location of the project", null); "Location path of the project", null);
define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID, define(MODE.INTEGER, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID,
"Target id to set for the project", null); "Target id to set for the project", -1);
define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "n", KEY_NAME,
"Project name", null);
} }
// -- some helpers for list action flags // -- some helpers for list action flags
@@ -123,9 +124,9 @@ public class SdkCommandLine extends CommandLineProcessor {
return ((String) getValue(ACTION_NEW_VM, KEY_SKIN)); return ((String) getValue(ACTION_NEW_VM, KEY_SKIN));
} }
/** Helper to retrieve the --sdcard name for the new vm action. */ /** Helper to retrieve the --sdcard data for the new vm action. */
public String getNewVmSdCard() { public String getNewVmSdCard() {
return ((String) getValue(ACTION_NEW_VM, KEY_SDCARD_PATH)); return ((String) getValue(ACTION_NEW_VM, KEY_SDCARD));
} }
@@ -167,4 +168,9 @@ public class SdkCommandLine extends CommandLineProcessor {
public int getUpdateProjectTargetId() { public int getUpdateProjectTargetId() {
return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue(); return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue();
} }
/** Helper to retrieve the --name for the update project action. */
public String getUpdateProjectName() {
return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_NAME));
}
} }

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkmanager;
import com.android.sdklib.ISdkLog;
/**
*
*/
public class MockStdLogger implements ISdkLog {
public void error(Throwable t, String errorFormat, Object... args) {
if (errorFormat != null) {
System.err.printf("Error: " + errorFormat, args);
if (!errorFormat.endsWith("\n")) {
System.err.printf("\n");
}
}
if (t != null) {
System.err.printf("Error: %s\n", t.getMessage());
}
}
public void warning(String warningFormat, Object... args) {
System.out.printf("Warning: " + warningFormat, args);
if (!warningFormat.endsWith("\n")) {
System.out.printf("\n");
}
}
public void printf(String msgFormat, Object... args) {
System.out.printf(msgFormat, args);
}
}

View File

@@ -31,6 +31,11 @@ import java.io.File;
*/ */
public final class SdkConstants { public final class SdkConstants {
/** An SDK Project's AndroidManifest.xml file */
public static final String FN_ANDROID_MANIFEST_XML= "AndroidManifest.xml";
/** An SDK Project's build.xml file */
public final static String FN_BUILD_XML = "build.xml";
/** Name of the framework library, i.e. "android.jar" */ /** Name of the framework library, i.e. "android.jar" */
public static final String FN_FRAMEWORK_LIBRARY = "android.jar"; public static final String FN_FRAMEWORK_LIBRARY = "android.jar";
/** Name of the layout attributes, i.e. "attrs.xml" */ /** Name of the layout attributes, i.e. "attrs.xml" */
@@ -129,7 +134,9 @@ public final class SdkConstants {
/** Name of the addon libs folder. */ /** Name of the addon libs folder. */
public final static String FD_ADDON_LIBS = "libs"; public final static String FD_ADDON_LIBS = "libs";
/** Namespace for the resource XML, i.e. "http://schemas.android.com/apk/res/android" */
public final static String NS_RESOURCES = "http://schemas.android.com/apk/res/android";
/* Folder path relative to the SDK root */ /* Folder path relative to the SDK root */
/** Path of the documentation directory relative to the sdk folder. /** Path of the documentation directory relative to the sdk folder.
* This is an OS path, ending with a separator. */ * This is an OS path, ending with a separator. */
@@ -206,7 +213,7 @@ public final class SdkConstants {
/** Returns the appropriate name for the 'android' command, which is 'android.bat' for /** Returns the appropriate name for the 'android' command, which is 'android.bat' for
* Windows and 'android' for all other platforms. */ * Windows and 'android' for all other platforms. */
public static String AndroidCmdName() { public static String androidCmdName() {
String os = System.getProperty("os.name"); String os = System.getProperty("os.name");
String cmd = "android"; String cmd = "android";
if (os.startsWith("Windows")) { if (os.startsWith("Windows")) {
@@ -215,4 +222,15 @@ public final class SdkConstants {
return cmd; return cmd;
} }
/** Returns the appropriate name for the 'mksdcard' command, which is 'mksdcard.exe' for
* Windows and 'mkdsdcard' for all other platforms. */
public static String mkSdCardCmdName() {
String os = System.getProperty("os.name");
String cmd = "mksdcard";
if (os.startsWith("Windows")) {
cmd += ".exe";
}
return cmd;
}
} }

View File

@@ -21,14 +21,27 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants; import com.android.sdklib.SdkConstants;
import com.android.sdklib.project.ProjectProperties.PropertyType; import com.android.sdklib.project.ProjectProperties.PropertyType;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
/** /**
* Creates the basic files needed to get an Android project up and running. Also * Creates the basic files needed to get an Android project up and running. Also
@@ -38,16 +51,31 @@ import java.util.Map;
*/ */
public class ProjectCreator { public class ProjectCreator {
/** Package path substitution string used in template files, i.e. "PACKAGE_PATH" */
private final static String PH_JAVA_FOLDER = "PACKAGE_PATH"; private final static String PH_JAVA_FOLDER = "PACKAGE_PATH";
/** Package name substitution string used in template files, i.e. "PACKAGE" */
private final static String PH_PACKAGE = "PACKAGE"; private final static String PH_PACKAGE = "PACKAGE";
/** Activity name substitution string used in template files, i.e. "ACTIVITY_NAME". */
private final static String PH_ACTIVITY_NAME = "ACTIVITY_NAME"; private final static String PH_ACTIVITY_NAME = "ACTIVITY_NAME";
/** Project name substitution string used in template files, i.e. "PROJECT_NAME". */
private final static String PH_PROJECT_NAME = "PROJECT_NAME";
private final static String FOLDER_TESTS = "tests"; private final static String FOLDER_TESTS = "tests";
public enum OutputLevel { public enum OutputLevel {
SILENT, NORMAL, VERBOSE; /** Silent mode. Project creation will only display errors. */
SILENT,
/** Normal mode. Project creation will display what's being done, display
* error but not warnings. */
NORMAL,
/** Verbose mode. Project creation will display what's being done, errors and warnings. */
VERBOSE;
} }
/**
* Exception thrown when a project creation fails, typically because a template
* file cannot be written.
*/
private static class ProjectCreateException extends Exception { private static class ProjectCreateException extends Exception {
/** default UID. This will not be serialized anyway. */ /** default UID. This will not be serialized anyway. */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -78,7 +106,8 @@ public class ProjectCreator {
/** /**
* Creates a new project. * Creates a new project.
* @param folderPath the folder of the project to create. This folder must exist. *
* @param folderPath the folder of the project to create.
* @param projectName the name of the project. * @param projectName the name of the project.
* @param packageName the package of the project. * @param packageName the package of the project.
* @param activityName the activity of the project as it will appear in the manifest. * @param activityName the activity of the project as it will appear in the manifest.
@@ -113,16 +142,16 @@ public class ProjectCreator {
try { try {
String[] content = projectFolder.list(); String[] content = projectFolder.list();
if (content == null) { if (content == null) {
error = "Project directory %1$s is not a directory."; error = "Project folder '%1$s' is not a directory.";
} else if (content.length != 0) { } else if (content.length != 0) {
error = "Project directory %1$s is not empty. Please consider using '%2$s update' instead."; error = "Project folder '%1$s' is not empty. Please consider using '%2$s update' instead.";
} }
} catch (Exception e1) { } catch (Exception e1) {
e = e1; e = e1;
} }
if (e != null || error != null) { if (e != null || error != null) {
mLog.error(e, error, projectFolder, SdkConstants.AndroidCmdName()); mLog.error(e, error, projectFolder, SdkConstants.androidCmdName());
} }
} }
@@ -164,6 +193,21 @@ public class ProjectCreator {
keywords.put(PH_ACTIVITY_NAME, activityName); keywords.put(PH_ACTIVITY_NAME, activityName);
} }
// Take the project name from the command line if there's one
if (projectName != null) {
keywords.put(PH_PROJECT_NAME, projectName);
} else {
if (activityName != null) {
// Use the activity as project name
keywords.put(PH_PROJECT_NAME, activityName);
} else {
// We need a project name. Just pick up the basename of the project
// directory.
projectName = projectFolder.getName();
keywords.put(PH_PROJECT_NAME, projectName);
}
}
// create the source folder and the java package folders. // create the source folder and the java package folders.
final String srcFolderPath = SdkConstants.FD_SOURCES + File.separator + packagePath; final String srcFolderPath = SdkConstants.FD_SOURCES + File.separator + packagePath;
File sourceFolder = createDirs(projectFolder, srcFolderPath); File sourceFolder = createDirs(projectFolder, srcFolderPath);
@@ -198,10 +242,13 @@ public class ProjectCreator {
manifestTemplate = "AndroidManifest.tests.template"; manifestTemplate = "AndroidManifest.tests.template";
} }
installTemplate(manifestTemplate, new File(projectFolder, "AndroidManifest.xml"), installTemplate(manifestTemplate,
new File(projectFolder, SdkConstants.FN_ANDROID_MANIFEST_XML),
keywords, target); keywords, target);
installTemplate("build.template", new File(projectFolder, "build.xml"), keywords); installTemplate("build.template",
new File(projectFolder, SdkConstants.FN_BUILD_XML),
keywords);
// if this is not a test project, then we create one. // if this is not a test project, then we create one.
if (isTestProject == false) { if (isTestProject == false) {
@@ -219,6 +266,293 @@ public class ProjectCreator {
} }
} }
/**
* Updates an existing project.
* <p/>
* Workflow:
* <ul>
* <li> Check AndroidManifest.xml is present (required)
* <li> Check there's a default.properties with a target *or* --target was specified
* <li> Update default.prop if --target was specified
* <li> Refresh/create "sdk" in local.properties
* <li> Build.xml: create if not present or no <androidinit(\w|/>) in it
* </ul>
*
* @param folderPath the folder of the project to update. This folder must exist.
* @param target the project target. Can be null.
* @param projectName The project name from --name. Can be null.
*/
public void updateProject(String folderPath, IAndroidTarget target, String projectName ) {
// project folder must exist and be a directory, since this is an update
File projectFolder = new File(folderPath);
if (!projectFolder.isDirectory()) {
mLog.error(null, "Project folder '%1$s' is not a valid directory, this is not an Android project you can update.",
projectFolder);
return;
}
// Check AndroidManifest.xml is present
File androidManifest = new File(projectFolder, SdkConstants.FN_ANDROID_MANIFEST_XML);
if (!androidManifest.isFile()) {
mLog.error(null,
"%1$s not found in '%2$s', this is not an Android project you can update.",
SdkConstants.FN_ANDROID_MANIFEST_XML,
folderPath);
return;
}
// Check there's a default.properties with a target *or* --target was specified
ProjectProperties props = ProjectProperties.load(folderPath, PropertyType.DEFAULT);
if (props == null || props.getProperty(ProjectProperties.PROPERTY_TARGET) == null) {
if (target == null) {
mLog.error(null,
"There is no %1$s file in '%2$s'. Please provide a --target to the '%3$s update' command.",
PropertyType.DEFAULT.getFilename(),
folderPath,
SdkConstants.androidCmdName());
return;
}
}
// Update default.prop iif --target was specified
if (target != null) {
props = ProjectProperties.create(folderPath, PropertyType.DEFAULT);
props.setAndroidTarget(target);
try {
props.save();
println("Updated %1$s", PropertyType.DEFAULT.getFilename());
} catch (IOException e) {
mLog.error(e, "Failed to write %1$s file in '%2$s'",
PropertyType.DEFAULT.getFilename(),
folderPath);
return;
}
}
// Refresh/create "sdk" in local.properties
props = ProjectProperties.create(folderPath, PropertyType.LOCAL);
props.setProperty(ProjectProperties.PROPERTY_SDK, mSdkFolder);
try {
props.save();
println("Updated %1$s", PropertyType.LOCAL.getFilename());
} catch (IOException e) {
mLog.error(e, "Failed to write %1$s file in '%2$s'",
PropertyType.LOCAL.getFilename(),
folderPath);
return;
}
// Build.xml: create if not present or no <androidinit/> in it
File buildXml = new File(projectFolder, SdkConstants.FN_BUILD_XML);
boolean needsBuildXml = projectName != null || !buildXml.exists();
if (!needsBuildXml) {
// Note that "<androidinit" must be followed by either a whitespace, a "/" (for the
// XML /> closing tag) or an end-of-line. This way we know the XML tag is really this
// one and later we will be able to use an "androidinit2" tag or such as necessary.
needsBuildXml = !checkFileContainsRegexp(buildXml, "<androidinit(?:\\s|/|$)");
if (needsBuildXml) {
println("File %1$s is too old and needs to be updated.", SdkConstants.FN_BUILD_XML);
}
}
if (needsBuildXml) {
// create the map for place-holders of values to replace in the templates
final HashMap<String, String> keywords = new HashMap<String, String>();
// Take the project name from the command line if there's one
if (projectName != null) {
keywords.put(PH_PROJECT_NAME, projectName);
} else {
extractPackageFromManifest(androidManifest, keywords);
if (keywords.containsKey(PH_ACTIVITY_NAME)) {
// Use the activity as project name
keywords.put(PH_PROJECT_NAME, keywords.get(PH_ACTIVITY_NAME));
} else {
// We need a project name. Just pick up the basename of the project
// directory.
projectName = projectFolder.getName();
keywords.put(PH_PROJECT_NAME, projectName);
}
}
if (mLevel == OutputLevel.VERBOSE) {
println("Regenerating %1$s with project name %2$s",
SdkConstants.FN_BUILD_XML,
keywords.get(PH_PROJECT_NAME));
}
try {
installTemplate("build.template",
new File(projectFolder, SdkConstants.FN_BUILD_XML),
keywords);
} catch (ProjectCreateException e) {
mLog.error(e, null);
}
}
}
/**
* Returns true if any line of the input file contains the requested regexp.
*/
private boolean checkFileContainsRegexp(File file, String regexp) {
Pattern p = Pattern.compile(regexp);
try {
BufferedReader in = new BufferedReader(new FileReader(file));
String line;
while ((line = in.readLine()) != null) {
if (p.matcher(line).find()) {
return true;
}
}
in.close();
} catch (Exception e) {
// ignore
}
return false;
}
/**
* Extracts a "full" package & activity name from an AndroidManifest.xml.
* <p/>
* The keywords dictionary is always filed the package name under the key {@link #PH_PACKAGE}.
* If an activity name can be found, it is filed under the key {@link #PH_ACTIVITY_NAME}.
* When no activity is found, this key is not created.
*
* @param manifestFile The AndroidManifest.xml file
* @param outKeywords Place where to put the out parameters: package and activity names.
* @return True if the package/activity was parsed and updated in the keyword dictionary.
*/
private boolean extractPackageFromManifest(File manifestFile,
Map<String, String> outKeywords) {
try {
final String nsPrefix = "android";
final String nsURI = SdkConstants.NS_RESOURCES;
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
if (nsPrefix.equals(prefix)) {
return nsURI;
}
return XMLConstants.NULL_NS_URI;
}
public String getPrefix(String namespaceURI) {
if (nsURI.equals(namespaceURI)) {
return nsPrefix;
}
return null;
}
@SuppressWarnings("unchecked")
public Iterator getPrefixes(String namespaceURI) {
if (nsURI.equals(namespaceURI)) {
ArrayList<String> list = new ArrayList<String>();
list.add(nsPrefix);
return list.iterator();
}
return null;
}
});
InputSource source = new InputSource(new FileReader(manifestFile));
String packageName = xpath.evaluate("/manifest/@package", source);
source = new InputSource(new FileReader(manifestFile));
// Select the "android:name" attribute of all <activity> nodes but only if they
// contain a sub-node <intent-filter><action> with an "android:name" attribute which
// is 'android.intent.action.MAIN' and an <intent-filter><category> with an
// "android:name" attribute which is 'android.intent.category.LAUNCHER'
String expression = String.format("/manifest/application/activity" +
"[intent-filter/action/@%1$s:name='android.intent.action.MAIN' and " +
"intent-filter/category/@%1$s:name='android.intent.category.LAUNCHER']" +
"/@%1$s:name", nsPrefix);
NodeList activityNames = (NodeList) xpath.evaluate(expression, source,
XPathConstants.NODESET);
// If we get here, both XPath expressions were valid so we're most likely dealing
// with an actual AndroidManifest.xml file. The nodes may not have the requested
// attributes though, if which case we should warn.
if (packageName == null || packageName.length() == 0) {
mLog.error(null,
"Missing <manifest package=\"...\"> in '%1$s'",
manifestFile.getName());
return false;
}
// Get the first activity that matched earlier. If there is no activity,
// activityName is set to an empty string and the generated "combined" name
// will be in the form "package." (with a dot at the end).
String activityName = "";
if (activityNames.getLength() > 0) {
activityName = activityNames.item(0).getNodeValue();
}
if (mLevel == OutputLevel.VERBOSE && activityNames.getLength() > 1) {
println("WARNING: There is more than one activity defined in '%1$s'.\n" +
"Only the first one will be used. If this is not appropriate, you need\n" +
"to specify one of these values manually instead:",
manifestFile.getName());
for (int i = 0; i < activityNames.getLength(); i++) {
String name = activityNames.item(i).getNodeValue();
name = combinePackageActivityNames(packageName, name);
println("- %1$s", name);
}
}
if (activityName.length() == 0) {
mLog.warning("Missing <activity %1$s:name=\"...\"> in '%2$s'.\n" +
"No activity will be generated.",
nsPrefix, manifestFile.getName());
} else {
outKeywords.put(PH_ACTIVITY_NAME, activityName);
}
outKeywords.put(PH_PACKAGE, packageName);
return true;
} catch (IOException e) {
mLog.error(e, "Failed to read %1$s", manifestFile.getName());
} catch (XPathExpressionException e) {
Throwable t = e.getCause();
mLog.error(t == null ? e : t,
"Failed to parse %1$s",
manifestFile.getName());
}
return false;
}
private String combinePackageActivityNames(String packageName, String activityName) {
// Activity Name can have 3 forms:
// - ".Name" means this is a class name in the given package name.
// The full FQCN is thus packageName + ".Name"
// - "Name" is an older variant of the former. Full FQCN is packageName + "." + "Name"
// - "com.blah.Name" is a full FQCN. Ignore packageName and use activityName as-is.
// To be valid, the package name should have at least two components. This is checked
// later during the creation of the build.xml file, so we just need to detect there's
// a dot but not at pos==0.
int pos = activityName.indexOf('.');
if (pos == 0) {
return packageName + activityName;
} else if (pos > 0) {
return activityName;
} else {
return packageName + "." + activityName;
}
}
/** /**
* Installs a new file that is based on a template file provided by a given target. * Installs a new file that is based on a template file provided by a given target.
* Each match of each key from the place-holder map in the template will be replaced with its * Each match of each key from the place-holder map in the template will be replaced with its
@@ -272,6 +606,9 @@ public class ProjectCreator {
*/ */
private void installFullPathTemplate(String sourcePath, File destFile, private void installFullPathTemplate(String sourcePath, File destFile,
Map<String, String> placeholderMap) throws ProjectCreateException { Map<String, String> placeholderMap) throws ProjectCreateException {
boolean existed = destFile.exists();
try { try {
BufferedWriter out = new BufferedWriter(new FileWriter(destFile)); BufferedWriter out = new BufferedWriter(new FileWriter(destFile));
BufferedReader in = new BufferedReader(new FileReader(sourcePath)); BufferedReader in = new BufferedReader(new FileReader(sourcePath));
@@ -293,17 +630,26 @@ public class ProjectCreator {
destFile, e.getMessage()); destFile, e.getMessage());
} }
println("Added file %1$s", destFile); println("%1$s file %2$s",
existed ? "Updated" : "Added",
destFile);
} }
/** /**
* Prints a message unless silence is enabled. * Prints a message unless silence is enabled.
* <p/>
* This is just a convenience wrapper around {@link ISdkLog#printf(String, Object...)} from
* {@link #mLog} after testing if ouput level is {@link OutputLevel#VERBOSE}.
*
* @param format Format for String.format * @param format Format for String.format
* @param args Arguments for String.format * @param args Arguments for String.format
*/ */
private void println(String format, Object... args) { private void println(String format, Object... args) {
if (mLevel == OutputLevel.VERBOSE) { if (mLevel != OutputLevel.SILENT) {
System.out.println(String.format(format, args)); if (!format.endsWith("\n")) {
format += "\n";
}
mLog.printf(format, args);
} }
} }

View File

@@ -47,6 +47,10 @@ public final class ProjectProperties {
mFilename = filename; mFilename = filename;
mHeader = header; mHeader = header;
} }
public String getFilename() {
return mFilename;
}
} }
private final static String LOCAL_HEADER = private final static String LOCAL_HEADER =

View File

@@ -20,14 +20,17 @@ import com.android.prefs.AndroidLocation;
import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog; import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager; import com.android.sdklib.SdkManager;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -42,13 +45,15 @@ public final class VmManager {
private final static String VM_INFO_PATH = "path"; private final static String VM_INFO_PATH = "path";
private final static String VM_INFO_TARGET = "target"; private final static String VM_INFO_TARGET = "target";
private final static String IMAGE_USERDATA = "userdata.img"; private final static String IMAGE_USERDATA = "userdata.img";
private final static String CONFIG_INI = "config.ini"; private final static String CONFIG_INI = "config.ini";
private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\.ini$", private final static Pattern INI_NAME_PATTERN = Pattern.compile("(.+)\\.ini$",
Pattern.CASE_INSENSITIVE); Pattern.CASE_INSENSITIVE);
private final static Pattern SDCARD_SIZE_PATTERN = Pattern.compile("\\d+[MK]?");
public static final class VmInfo { public static final class VmInfo {
String name; String name;
String path; String path;
@@ -69,10 +74,12 @@ public final class VmManager {
private final ArrayList<VmInfo> mVmList = new ArrayList<VmInfo>(); private final ArrayList<VmInfo> mVmList = new ArrayList<VmInfo>();
private ISdkLog mSdkLog; private ISdkLog mSdkLog;
private final SdkManager mSdk;
public VmManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException { public VmManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
mSdk = sdk;
mSdkLog = sdkLog; mSdkLog = sdkLog;
buildVmList(sdk); buildVmList();
} }
/** /**
@@ -104,12 +111,12 @@ public final class VmManager {
* @param name the name of the VM * @param name the name of the VM
* @param target the target of the VM * @param target the target of the VM
* @param skinName the name of the skin. Can be null. * @param skinName the name of the skin. Can be null.
* @param sdcardPath the path to the sdCard. Can be null. * @param sdcard the parameter value for the sdCard. Can be null. This is either a path to
* @param sdcardSize the size of a local sdcard to create. Can be 0 for no local sdcard. * an existing sdcard image or a sdcard size (\d+, \d+K, \dM).
* @param hardwareConfig the hardware setup for the VM * @param hardwareConfig the hardware setup for the VM
*/ */
public VmInfo createVm(String parentFolder, String name, IAndroidTarget target, public VmInfo createVm(String parentFolder, String name, IAndroidTarget target,
String skinName, String sdcardPath, int sdcardSize, Map<String,String> hardwareConfig, String skinName, String sdcard, Map<String,String> hardwareConfig,
ISdkLog log) { ISdkLog log) {
try { try {
@@ -128,7 +135,7 @@ public final class VmManager {
} }
return null; return null;
} }
// create the vm folder. // create the vm folder.
vmFolder.mkdir(); vmFolder.mkdir();
@@ -177,15 +184,40 @@ public final class VmManager {
} }
} }
if (sdcardPath != null) { if (sdcard != null) {
File sdcard = new File(sdcardPath); File sdcardFile = new File(sdcard);
if (sdcard.isFile()) { if (sdcardFile.isFile()) {
values.put("sdcard", sdcardPath); values.put("sdcard", sdcard);
} else if (log != null) { } else {
log.warning("sdcarad image '%1$s' does not exists.", sdcardPath); // check that it matches the pattern for sdcard size
Matcher m = SDCARD_SIZE_PATTERN.matcher(sdcard);
if (m.matches()) {
// create the sdcard.
sdcardFile = new File(vmFolder, "sdcard.img");
String path = sdcardFile.getAbsolutePath();
// execute mksdcard with the proper parameters.
File toolsFolder = new File(mSdk.getLocation(), SdkConstants.FD_TOOLS);
File mkSdCard = new File(toolsFolder, SdkConstants.mkSdCardCmdName());
if (mkSdCard.isFile() == false) {
log.error(null, "'%1$s' is missing from the SDK tools folder.",
mkSdCard.getName());
return null;
}
if (createSdCard(mkSdCard.getAbsolutePath(), sdcard, path, log) == false) {
return null; // mksdcard output has already been displayed, no need to
// output anything else.
}
// add its path to the values.
values.put("sdcard", path);
} else {
log.error(null, "'%1$s' is not recognized as a valid sdcard value", sdcard);
return null;
}
} }
} else if (sdcardSize != 0) {
// TODO: create sdcard image.
} }
if (hardwareConfig != null) { if (hardwareConfig != null) {
@@ -227,7 +259,7 @@ public final class VmManager {
return null; return null;
} }
private void buildVmList(SdkManager sdk) throws AndroidLocationException { private void buildVmList() throws AndroidLocationException {
// get the Android prefs location. // get the Android prefs location.
String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS; String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
@@ -253,14 +285,14 @@ public final class VmManager {
}); });
for (File vm : vms) { for (File vm : vms) {
VmInfo info = parseVmInfo(vm, sdk); VmInfo info = parseVmInfo(vm);
if (info != null) { if (info != null) {
mVmList.add(info); mVmList.add(info);
} }
} }
} }
private VmInfo parseVmInfo(File path, SdkManager sdk) { private VmInfo parseVmInfo(File path) {
Map<String, String> map = SdkManager.parsePropertyFile(path, mSdkLog); Map<String, String> map = SdkManager.parsePropertyFile(path, mSdkLog);
String vmPath = map.get(VM_INFO_PATH); String vmPath = map.get(VM_INFO_PATH);
@@ -273,7 +305,7 @@ public final class VmManager {
return null; return null;
} }
IAndroidTarget target = sdk.getTargetFromHashString(targetHash); IAndroidTarget target = mSdk.getTargetFromHashString(targetHash);
if (target == null) { if (target == null) {
return null; return null;
} }
@@ -301,4 +333,118 @@ public final class VmManager {
writer.close(); writer.close();
} }
private boolean createSdCard(String toolLocation, String size, String location, ISdkLog log) {
try {
String[] command = new String[3];
command[0] = toolLocation;
command[1] = size;
command[2] = location;
Process process = Runtime.getRuntime().exec(command);
ArrayList<String> errorOutput = new ArrayList<String>();
ArrayList<String> stdOutput = new ArrayList<String>();
int status = grabProcessOutput(process, errorOutput, stdOutput,
true /* waitForReaders */);
if (status != 0) {
log.error(null, "Failed to create the SD card.");
for (String error : errorOutput) {
log.error(null, error);
}
return false;
}
return true;
} catch (InterruptedException e) {
log.error(null, "Failed to create the SD card.");
} catch (IOException e) {
log.error(null, "Failed to create the SD card.");
}
return false;
}
/**
* Gets the stderr/stdout outputs of a process and returns when the process is done.
* Both <b>must</b> be read or the process will block on windows.
* @param process The process to get the ouput from
* @param errorOutput The array to store the stderr output. cannot be null.
* @param stdOutput The array to store the stdout output. cannot be null.
* @param waitforReaders if true, this will wait for the reader threads.
* @return the process return code.
* @throws InterruptedException
*/
private int grabProcessOutput(final Process process, final ArrayList<String> errorOutput,
final ArrayList<String> stdOutput, boolean waitforReaders)
throws InterruptedException {
assert errorOutput != null;
assert stdOutput != null;
// read the lines as they come. if null is returned, it's
// because the process finished
Thread t1 = new Thread("") { //$NON-NLS-1$
@Override
public void run() {
// create a buffer to read the stderr output
InputStreamReader is = new InputStreamReader(process.getErrorStream());
BufferedReader errReader = new BufferedReader(is);
try {
while (true) {
String line = errReader.readLine();
if (line != null) {
errorOutput.add(line);
} else {
break;
}
}
} catch (IOException e) {
// do nothing.
}
}
};
Thread t2 = new Thread("") { //$NON-NLS-1$
@Override
public void run() {
InputStreamReader is = new InputStreamReader(process.getInputStream());
BufferedReader outReader = new BufferedReader(is);
try {
while (true) {
String line = outReader.readLine();
if (line != null) {
stdOutput.add(line);
} else {
break;
}
}
} catch (IOException e) {
// do nothing.
}
}
};
t1.start();
t2.start();
// it looks like on windows process#waitFor() can return
// before the thread have filled the arrays, so we wait for both threads and the
// process itself.
if (waitforReaders) {
try {
t1.join();
} catch (InterruptedException e) {
}
try {
t2.join();
} catch (InterruptedException e) {
}
}
// get the return code from the process
return process.waitFor();
}
} }