auto import from //branches/cupcake/...@127101
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -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.
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
2
pdk/doxygen_config/footer.html
Normal file
2
pdk/doxygen_config/footer.html
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
</body>
|
||||||
|
</html>
|
||||||
15
pdk/doxygen_config/header.html
Normal file
15
pdk/doxygen_config/header.html
Normal 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>
|
||||||
@@ -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) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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
|
|
||||||
@@ -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)
|
|
||||||
|
|
||||||
@@ -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 "$@"
|
|
||||||
@@ -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 %*
|
|
||||||
@@ -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)
|
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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$
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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$
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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 */);
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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$
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 #"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 =
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user