- Added new Bottom Navigation, Tabbed, Fragment + ViewModel, Native C++ project templates - Fixed #227 (NPE trying to set message to ProgressSheet) - Updated template images
@@ -152,8 +152,9 @@ public class AboutActivity extends StudioActivity {
|
||||
licenses.add(
|
||||
new License("JavaPoet", "Apache License 2.0", "https://github.com/square/JavaPoet"));
|
||||
licenses.add(
|
||||
new License("Zip4j", "Apache License 2.0", "https://github.com/srikanth-lingala/zip4j"));
|
||||
|
||||
new License("Zip4j", "Apache License 2.0", "https://github.com/srikanth-lingala/zip4j"));
|
||||
licenses.add(new License("Android Studio", "Apache License 2.0", "https://cs.android.com/android-studio"));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (License license : licenses) {
|
||||
sb.append("\u2022 ");
|
||||
|
||||
@@ -13,9 +13,9 @@ import android.widget.AutoCompleteTextView;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.transition.TransitionManager;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.google.android.material.transition.MaterialFadeThrough;
|
||||
import com.google.android.material.transition.MaterialSharedAxis;
|
||||
@@ -29,13 +29,10 @@ import com.itsaky.androidide.databinding.SetupFooterBinding;
|
||||
import com.itsaky.androidide.databinding.WizardDetailsBinding;
|
||||
import com.itsaky.androidide.databinding.WizardTemplatesBinding;
|
||||
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
|
||||
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
|
||||
import com.itsaky.androidide.managers.PreferenceManager;
|
||||
import com.itsaky.androidide.models.NewProjectDetails;
|
||||
import com.itsaky.androidide.models.ProjectTemplate;
|
||||
import com.itsaky.androidide.tasks.TaskExecutor;
|
||||
import com.itsaky.androidide.tasks.callables.ProjectCreatorCallable;
|
||||
import com.itsaky.androidide.utils.AndroidUtils;
|
||||
import com.itsaky.androidide.utils.DialogUtils;
|
||||
import com.itsaky.androidide.utils.Environment;
|
||||
import com.itsaky.androidide.utils.FileUtil;
|
||||
import com.itsaky.androidide.utils.SingleTextWatcher;
|
||||
@@ -45,10 +42,11 @@ import com.itsaky.toaster.Toaster;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WizardFragment extends BaseFragment implements ProjectWriterCallback {
|
||||
public class WizardFragment extends BaseFragment {
|
||||
|
||||
public static final String TAG = "WizardFragmentTag";
|
||||
public static final String PREF_PACKAGE_DOMAIN_KEY = "pref_package_domain";
|
||||
@@ -134,6 +132,36 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
}
|
||||
});
|
||||
|
||||
mViewModel
|
||||
.getStatusMessage()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(message) -> {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
setMessage(message);
|
||||
});
|
||||
|
||||
mViewModel
|
||||
.getErrorState()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(message) -> {
|
||||
if (mProgressSheet != null && mProgressSheet.isShowing()) {
|
||||
mProgressSheet.dismiss();
|
||||
}
|
||||
StudioApp.getInstance().toast(message, Toaster.Type.ERROR);
|
||||
});
|
||||
|
||||
mViewModel
|
||||
.getFileCreatedState()
|
||||
.observe(
|
||||
getViewLifecycleOwner(),
|
||||
(file) -> {
|
||||
if (file != null) onSuccess(file);
|
||||
});
|
||||
|
||||
mAdapter.setOnItemClickListener(
|
||||
(item, pos) -> {
|
||||
mCurrentTemplate = item;
|
||||
@@ -197,9 +225,8 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
|
||||
private boolean validateDetails() {
|
||||
|
||||
verifyAppName(detailsBinding.tilAppName.getEditText().getText(), false);
|
||||
verifyPackageName(detailsBinding.tilPackageName.getEditText().getText());
|
||||
verifyAppName(detailsBinding.tilAppName.getEditText().getText());
|
||||
|
||||
if (detailsBinding.tilPackageName.isErrorEnabled()) {
|
||||
return false;
|
||||
}
|
||||
@@ -221,12 +248,22 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
final int targetSdk = getTargetSdk();
|
||||
final String savePath = detailsBinding.etSaveLocation.getText().toString().trim();
|
||||
final String projectLanguage = detailsBinding.etLanguage.getText().toString();
|
||||
final String cppToolChain =
|
||||
getCppToolchans().get(detailsBinding.etToolchain.getText().toString());
|
||||
|
||||
PreferenceManager manager = StudioApp.getInstance().getPrefManager();
|
||||
manager.putInt(PREF_MIN_SDK_INDEX_KEY, minSdkIndex);
|
||||
manager.putInt(PREF_TERGET_SDK_INDEX_KEY, targetSdkIndex);
|
||||
manager.putString(PREF_PACKAGE_DOMAIN_KEY, AndroidUtils.getPackageDomain(packageName));
|
||||
createProject(appName, packageName, minSdk, targetSdk, projectLanguage, savePath);
|
||||
mViewModel.createProject(
|
||||
mCurrentTemplate,
|
||||
appName,
|
||||
packageName,
|
||||
minSdk,
|
||||
targetSdk,
|
||||
projectLanguage,
|
||||
cppToolChain,
|
||||
savePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +288,15 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
"API 32: Android 12.1L (S)");
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, String> getCppToolchans() {
|
||||
LinkedHashMap<String, String> cppStandartType = new LinkedHashMap<>();
|
||||
cppStandartType.put("Toolchain Default", "");
|
||||
cppStandartType.put("C++11", "-std=c++11");
|
||||
cppStandartType.put("C++14", "-std=c++14");
|
||||
cppStandartType.put("C++17", "-std=c++17");
|
||||
return cppStandartType;
|
||||
}
|
||||
|
||||
private void onNavigateBack() {
|
||||
if (!mLast) {
|
||||
getParentFragmentManager().popBackStack();
|
||||
@@ -278,6 +324,7 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
templatesBinding.getRoot().setVisibility(View.GONE);
|
||||
detailsBinding.getRoot().setVisibility(View.GONE);
|
||||
templatesBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
detailsBinding.tilToolchain.setVisibility(View.GONE);
|
||||
footerBinding.nextButton.setVisibility(View.GONE);
|
||||
footerBinding.nextButton.setText(R.string.next);
|
||||
footerBinding.exitButton.setText(R.string.exit);
|
||||
@@ -300,11 +347,6 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
detailsBinding.etAppName.setText("My Application");
|
||||
String domain = manager.getString(PREF_PACKAGE_DOMAIN_KEY, "com.example");
|
||||
detailsBinding.etPackageName.setText(domain + ".myapplication");
|
||||
detailsBinding.etLanguage.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
languages));
|
||||
|
||||
if (languages.size() == 1) {
|
||||
detailsBinding.tilLanguage.setEnabled(false);
|
||||
@@ -312,10 +354,31 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
detailsBinding.tilLanguage.setEnabled(true);
|
||||
}
|
||||
|
||||
detailsBinding.etLanguage.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
languages));
|
||||
|
||||
detailsBinding.etLanguage.setListSelection(0);
|
||||
|
||||
if (mCurrentTemplate.isCpp()) {
|
||||
detailsBinding.tilToolchain.setVisibility(View.VISIBLE);
|
||||
detailsBinding.etToolchain.setAdapter(
|
||||
new ArrayAdapter<>(
|
||||
requireContext(),
|
||||
androidx.appcompat.R.layout.support_simple_spinner_dropdown_item,
|
||||
getCppToolchans().keySet().toArray(new String[getCppToolchans().size()])));
|
||||
|
||||
detailsBinding.etToolchain.setListSelection(0);
|
||||
detailsBinding.etToolchain.setText(getSelectedItem(0, detailsBinding.etToolchain), false);
|
||||
|
||||
showDialogNdkNotSupportedOfficially();
|
||||
}
|
||||
|
||||
detailsBinding.etLanguage.setText(getSelectedItem(0, detailsBinding.etLanguage), false);
|
||||
minSdkIndex = manager.getInt(PREF_MIN_SDK_INDEX_KEY, 5);
|
||||
|
||||
|
||||
// google recommended use latest target sdk version
|
||||
targetSdkIndex = manager.getInt(PREF_TERGET_SDK_INDEX_KEY, getSdks().size() - 1);
|
||||
detailsBinding.etMinSdk.setListSelection(minSdkIndex);
|
||||
@@ -352,7 +415,7 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
new SingleTextWatcher() {
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
verifyAppName(editable);
|
||||
verifyAppName(editable, true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -436,7 +499,7 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAppName(Editable editable) {
|
||||
private void verifyAppName(Editable editable, boolean isAddToPackage) {
|
||||
String name = editable.toString().trim();
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
detailsBinding.tilAppName.setError(getString(R.string.wizard_error_name_empty));
|
||||
@@ -447,58 +510,24 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
} else {
|
||||
detailsBinding.tilAppName.setErrorEnabled(false);
|
||||
}
|
||||
|
||||
setPackageName(name);
|
||||
if (isAddToPackage) {
|
||||
setPackageName(name);
|
||||
}
|
||||
setSaveLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeBegin() {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
|
||||
setMessage(R.string.msg_begin_project_write);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessTask(String taskName) {
|
||||
setMessage(taskName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File root) {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
|
||||
if (mProgressSheet.isShowing()) {
|
||||
if (mProgressSheet != null && mProgressSheet.isShowing()) {
|
||||
mProgressSheet.dismiss();
|
||||
}
|
||||
StudioApp.getInstance().toast(R.string.project_created_successfully, Toaster.Type.SUCCESS);
|
||||
|
||||
if (getActivity() != null && mListener != null) {
|
||||
requireActivity()
|
||||
.runOnUiThread(
|
||||
() -> {
|
||||
getParentFragmentManager().popBackStack();
|
||||
mListener.openProject(root);
|
||||
});
|
||||
if (mListener != null) {
|
||||
getParentFragmentManager().popBackStack();
|
||||
mListener.openProject(root);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(String reason) {
|
||||
if (mProgressSheet == null) {
|
||||
createProgressSheet();
|
||||
}
|
||||
|
||||
if (mProgressSheet.isShowing()) {
|
||||
mProgressSheet.dismiss();
|
||||
}
|
||||
StudioApp.getInstance().toast(reason, Toaster.Type.ERROR);
|
||||
}
|
||||
|
||||
private void createProgressSheet() {
|
||||
mProgressSheet = new ProgressSheet();
|
||||
mProgressSheet.setShowShadow(false);
|
||||
@@ -511,22 +540,16 @@ public class WizardFragment extends BaseFragment implements ProjectWriterCallbac
|
||||
private void setMessage(String msg) {
|
||||
mProgressSheet.setMessage(msg);
|
||||
}
|
||||
|
||||
private void createProject(
|
||||
String appName,
|
||||
String packageName,
|
||||
int minSdk,
|
||||
int targetSdk,
|
||||
String language,
|
||||
String savePath) {
|
||||
new TaskExecutor()
|
||||
.executeAsync(
|
||||
new ProjectCreatorCallable(
|
||||
mCurrentTemplate,
|
||||
new NewProjectDetails(appName, packageName, minSdk, targetSdk, language, savePath),
|
||||
this),
|
||||
r -> {});
|
||||
}
|
||||
|
||||
private void showDialogNdkNotSupportedOfficially(){
|
||||
DialogUtils.newMaterialDialogBuilder(requireContext())
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(R.string.title_warning)
|
||||
.setMessage(R.string.msg_ndk_currently_unsupported)
|
||||
.setCancelable(false)
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
public interface OnProjectCreatedListener {
|
||||
void openProject(File project);
|
||||
|
||||
@@ -25,15 +25,24 @@ public class NewProjectDetails {
|
||||
public int targetSdk;
|
||||
public String language;
|
||||
public String savePath;
|
||||
public String cppFlags;
|
||||
|
||||
public NewProjectDetails() {}
|
||||
|
||||
public NewProjectDetails(String name, String packageName, int minSdk, int targetSdk, String language, String savePath) {
|
||||
public NewProjectDetails(
|
||||
String name,
|
||||
String packageName,
|
||||
int minSdk,
|
||||
int targetSdk,
|
||||
String language,
|
||||
String cppFlags,
|
||||
String savePath) {
|
||||
this.name = name;
|
||||
this.packageName = packageName;
|
||||
this.minSdk = minSdk;
|
||||
this.targetSdk = targetSdk;
|
||||
this.language = language;
|
||||
this.cppFlags = cppFlags;
|
||||
this.savePath = savePath;
|
||||
}
|
||||
|
||||
@@ -72,4 +81,13 @@ public class NewProjectDetails {
|
||||
public int getTargetSdk() {
|
||||
return targetSdk;
|
||||
}
|
||||
|
||||
public NewProjectDetails setCppFlags(String cppFlags) {
|
||||
this.cppFlags = cppFlags;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getCppFlags() {
|
||||
return cppFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public class ProjectTemplate {
|
||||
private String description;
|
||||
private boolean isSupportJava;
|
||||
private boolean isSupportKotlin;
|
||||
private boolean isCpp;
|
||||
|
||||
@DrawableRes private int imageId;
|
||||
|
||||
@@ -89,7 +90,6 @@ public class ProjectTemplate {
|
||||
return this.isSupportJava;
|
||||
}
|
||||
|
||||
|
||||
public ProjectTemplate setSupportJava(boolean isSupportJava) {
|
||||
this.isSupportJava = isSupportJava;
|
||||
return this;
|
||||
@@ -103,4 +103,13 @@ public class ProjectTemplate {
|
||||
this.isSupportKotlin = isSupportKotlin;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isCpp() {
|
||||
return this.isCpp;
|
||||
}
|
||||
|
||||
public ProjectTemplate setIsCpp(boolean isCpp) {
|
||||
this.isCpp = isCpp;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,11 +50,14 @@ public class ProjectWriter {
|
||||
|
||||
private static final String XML_TEMPLATE_PATH = "templates/xml";
|
||||
private static final String SOURCE_PATH_REGEX = "/.*/src/.*/java|kt";
|
||||
private static final String FILE_EXT_REGEX = ".*/java|kt|gradle|xml";
|
||||
private static final String FILE_EXT_REGEX = ".*/java|kt|gradle|xml|txt|cpp";
|
||||
private static final String APP_NAME = "$app_name",
|
||||
PACKAGE_NAME = "$package_name",
|
||||
MIN_SDK = "$min_sdk",
|
||||
TARGET_SDK = "$target_sdk";
|
||||
TARGET_SDK = "$target_sdk",
|
||||
PACKAGE_NAME_CPP = "{$package_name_cpp}",
|
||||
CPP_FLAGS = "$cpp_flags",
|
||||
LIBRARY_NAME = "$library_name";
|
||||
|
||||
@NonNull
|
||||
public static String createMenu() {
|
||||
@@ -211,12 +214,23 @@ public class ProjectWriter {
|
||||
Matcher extMatcher = Pattern.compile(FILE_EXT_REGEX).matcher(name);
|
||||
if (extMatcher.find()) {
|
||||
String fileContent = FileIOUtils.readFile2String(unzipFile);
|
||||
|
||||
fileContent = customReplaceAll(fileContent, APP_NAME, details.name);
|
||||
fileContent =
|
||||
fileContent
|
||||
.replace(APP_NAME, details.name)
|
||||
.replace(PACKAGE_NAME, details.packageName)
|
||||
.replace(MIN_SDK, String.valueOf(details.minSdk))
|
||||
.replace(TARGET_SDK, String.valueOf(details.targetSdk));
|
||||
customReplaceAll(
|
||||
fileContent,
|
||||
PACKAGE_NAME_CPP,
|
||||
String.valueOf(details.packageName.replace("_", "_1").replace('.', '_')));
|
||||
fileContent = customReplaceAll(fileContent, PACKAGE_NAME, details.packageName);
|
||||
fileContent = customReplaceAll(fileContent, MIN_SDK, String.valueOf(details.minSdk));
|
||||
fileContent =
|
||||
customReplaceAll(fileContent, TARGET_SDK, String.valueOf(details.targetSdk));
|
||||
fileContent = customReplaceAll(fileContent, CPP_FLAGS, details.cppFlags);
|
||||
fileContent =
|
||||
customReplaceAll(
|
||||
fileContent,
|
||||
LIBRARY_NAME,
|
||||
details.packageName.substring(details.packageName.lastIndexOf('.') + 1));
|
||||
if (!FileIOUtils.writeFileFromString(unzipFile, fileContent, false)) {
|
||||
notifyFailed(instance.getString(R.string.failed_write_file, unzipFile.getName()));
|
||||
}
|
||||
@@ -229,6 +243,32 @@ public class ProjectWriter {
|
||||
}
|
||||
}
|
||||
|
||||
public static String customReplaceAll(String str, String oldStr, String newStr) {
|
||||
|
||||
if ("".equals(str) || "".equals(oldStr) || oldStr.equals(newStr)) {
|
||||
return str;
|
||||
}
|
||||
if (newStr == null) {
|
||||
newStr = "";
|
||||
}
|
||||
final int strLength = str.length();
|
||||
final int oldStrLength = oldStr.length();
|
||||
StringBuilder builder = new StringBuilder(str);
|
||||
|
||||
for (int i = 0; i < strLength; i++) {
|
||||
int index = builder.indexOf(oldStr, i);
|
||||
|
||||
if (index == -1) {
|
||||
if (i == 0) {
|
||||
return str;
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
builder = builder.replace(index, index + oldStrLength, newStr);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static void notifyBegin() {
|
||||
ThreadUtils.runOnUiThread(
|
||||
() -> {
|
||||
|
||||
@@ -10,8 +10,13 @@ import androidx.lifecycle.MutableLiveData;
|
||||
import com.blankj.utilcode.util.CollectionUtils;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
|
||||
import com.itsaky.androidide.models.NewProjectDetails;
|
||||
import com.itsaky.androidide.models.ProjectTemplate;
|
||||
|
||||
import com.itsaky.androidide.tasks.TaskExecutor;
|
||||
import com.itsaky.androidide.tasks.callables.ProjectCreatorCallable;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -21,6 +26,9 @@ public class WizardViewModel extends AndroidViewModel {
|
||||
private MutableLiveData<List<ProjectTemplate>> mProjectTemplatesList =
|
||||
new MutableLiveData<>(CollectionUtils.newArrayList());
|
||||
private MutableLiveData<Boolean> mLoadingState = new MutableLiveData<>(true);
|
||||
private MutableLiveData<String> mErrorMessageState = new MutableLiveData<>();
|
||||
private MutableLiveData<String> mMessageState = new MutableLiveData<>();
|
||||
private MutableLiveData<File> mCreatedProject = new MutableLiveData<>(null);
|
||||
|
||||
public WizardViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
@@ -43,7 +51,7 @@ public class WizardViewModel extends AndroidViewModel {
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_empty)
|
||||
.setImageId(R.drawable.template_empty),
|
||||
.setImageId(R.drawable.template_empty_activity),
|
||||
basic =
|
||||
new ProjectTemplate()
|
||||
.setId(1)
|
||||
@@ -54,7 +62,7 @@ public class WizardViewModel extends AndroidViewModel {
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_basic)
|
||||
.setImageId(R.drawable.template_basic),
|
||||
.setImageId(R.drawable.template_basic_activity),
|
||||
drawer =
|
||||
new ProjectTemplate()
|
||||
.setId(2)
|
||||
@@ -66,33 +74,70 @@ public class WizardViewModel extends AndroidViewModel {
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_navigation_drawer)
|
||||
.setImageId(R.drawable.template_navigation_drawer),
|
||||
libgdx =
|
||||
.setImageId(R.drawable.template_blank_activity_drawer),
|
||||
bottomTabs =
|
||||
new ProjectTemplate()
|
||||
.setId(3)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(), R.string.template_libgdx)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_libgdx)
|
||||
.setImageId(R.drawable.template_libgdx),
|
||||
compose =
|
||||
R.string.template_navigation_tabs)
|
||||
.setImageId(R.drawable.template_bottom_navigation_activity),
|
||||
tabs =
|
||||
new ProjectTemplate()
|
||||
.setId(4)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_tabs)
|
||||
.setImageId(R.drawable.template_blank_activity_tabs),
|
||||
fragmentViewModel =
|
||||
new ProjectTemplate()
|
||||
.setId(5)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_fragment_and_viewmodel)
|
||||
.setImageId(R.drawable.template_empty_activity),
|
||||
cppWizard =
|
||||
new ProjectTemplate()
|
||||
.setId(6)
|
||||
.setSupportJava(true)
|
||||
.setSupportKotlin(true)
|
||||
.setIsCpp(true)
|
||||
.setName(getApplication().getApplicationContext(), R.string.template_cpp)
|
||||
.setImageId(R.drawable.template_cpp_configure),
|
||||
compose =
|
||||
new ProjectTemplate()
|
||||
.setId(7)
|
||||
.setSupportKotlin(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(), R.string.template_compose)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_compose)
|
||||
.setImageId(R.drawable.template_kotlin);
|
||||
|
||||
.setImageId(R.drawable.template_compose_empty_activity),
|
||||
libgdx =
|
||||
new ProjectTemplate()
|
||||
.setId(8)
|
||||
.setSupportJava(true)
|
||||
.setName(
|
||||
getApplication().getApplicationContext(), R.string.template_libgdx)
|
||||
.setDescription(
|
||||
getApplication().getApplicationContext(),
|
||||
R.string.template_description_libgdx)
|
||||
.setImageId(R.drawable.template_game_activity);
|
||||
|
||||
mTemplates.add(empty);
|
||||
mTemplates.add(basic);
|
||||
mTemplates.add(drawer);
|
||||
mTemplates.add(libgdx);
|
||||
mTemplates.add(bottomTabs);
|
||||
mTemplates.add(tabs);
|
||||
mTemplates.add(fragmentViewModel);
|
||||
mTemplates.add(cppWizard);
|
||||
mTemplates.add(compose);
|
||||
mTemplates.add(libgdx);
|
||||
|
||||
mProjectTemplatesList.postValue(mTemplates);
|
||||
mLoadingState.postValue(false);
|
||||
@@ -106,4 +151,57 @@ public class WizardViewModel extends AndroidViewModel {
|
||||
public LiveData<Boolean> getLoadingState() {
|
||||
return mLoadingState;
|
||||
}
|
||||
|
||||
public LiveData<String> getErrorState() {
|
||||
return mErrorMessageState;
|
||||
}
|
||||
|
||||
public LiveData<File> getFileCreatedState() {
|
||||
return mCreatedProject;
|
||||
}
|
||||
|
||||
public LiveData<String> getStatusMessage() {
|
||||
return mMessageState;
|
||||
}
|
||||
|
||||
public void createProject(
|
||||
ProjectTemplate currentTemplate,
|
||||
String appName,
|
||||
String packageName,
|
||||
int minSdk,
|
||||
int targetSdk,
|
||||
String language,
|
||||
String cppFlags,
|
||||
String savePath) {
|
||||
new TaskExecutor()
|
||||
.executeAsync(
|
||||
new ProjectCreatorCallable(
|
||||
currentTemplate,
|
||||
new NewProjectDetails(
|
||||
appName, packageName, minSdk, targetSdk, language, cppFlags, savePath),
|
||||
new ProjectWriterCallback() {
|
||||
|
||||
@Override
|
||||
public void beforeBegin() {
|
||||
mMessageState.setValue(
|
||||
getApplication().getString(R.string.msg_begin_project_write));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessTask(String arg0) {
|
||||
mMessageState.setValue(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(File arg0) {
|
||||
mCreatedProject.setValue(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(String arg0) {
|
||||
mErrorMessageState.setValue(arg0);
|
||||
}
|
||||
}),
|
||||
r -> {});
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 56 KiB |
@@ -75,8 +75,8 @@
|
||||
android:id="@+id/et_save_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:ellipsize="start" />
|
||||
android:ellipsize="start"
|
||||
android:inputType="textNoSuggestions" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
@@ -98,7 +98,7 @@
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_min_sdk"
|
||||
android:id="@+id/til_toolchain"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -106,6 +106,25 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_language"
|
||||
android:hint="@string/wizard_toolchain"
|
||||
android:visibility="gone" >
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/et_toolchain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/til_min_sdk"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/til_toolchain"
|
||||
android:hint="@string/minimum_sdk"
|
||||
app:startIconDrawable="@drawable/ic_min_sdk"
|
||||
app:startIconTint="@color/primaryIconColor" >
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
|
||||
<!-- AndroidIDE -->
|
||||
@@ -21,7 +22,7 @@
|
||||
<string name="share_with_friends">Share with Friends</string>
|
||||
<string name="ide_preferences">IDE preferences</string>
|
||||
<string name="discussions_on_telegram">Discussions on Telegram</string>
|
||||
<string name="msg_empty_view">I have nothing to show you…</string>
|
||||
<string name="msg_empty_view">I have nothing to show you…</string>
|
||||
<string name="btn_terminal">Terminal</string>
|
||||
<string name="reset">Reset</string>
|
||||
<string name="app_logs">App Logs</string>
|
||||
@@ -31,12 +32,12 @@
|
||||
|
||||
<!-- LSP, Diagnostics & Completions -->
|
||||
<string name="msg_cannot_perform_fix">Unable to perform quick fix</string>
|
||||
<string name="msg_performing_actions">Performing code action…</string>
|
||||
<string name="msg_performing_actions">Performing code action…</string>
|
||||
<string name="msg_api_info_since">Since API %d</string>
|
||||
<string name="msg_api_info_removed">Removed in API %d</string>
|
||||
<string name="msg_api_info_deprecated">Deprecated in API %d</string>
|
||||
<string name="msg_finding_references">Finding references…</string>
|
||||
<string name="msg_finding_definition">Finding definition…</string>
|
||||
<string name="msg_finding_references">Finding references…</string>
|
||||
<string name="msg_finding_definition">Finding definition…</string>
|
||||
<string name="msg_no_definition">Definition not found</string>
|
||||
<string name="msg_no_references">No references found</string>
|
||||
<string name="view_diags">Diagnostics</string>
|
||||
@@ -46,7 +47,7 @@
|
||||
<string name="get_ready_for_something_awesome">Get ready for something awesome !</string>
|
||||
<string name="msg_picked_isnt_dir">Picked file is not a directory!</string>
|
||||
<string name="msg_pick_single_file">Please choose only one directory</string>
|
||||
<string name="please_wait">Please wait for a moment …</string>
|
||||
<string name="please_wait">Please wait for a moment …</string>
|
||||
<string name="title_device_not_supported">Device Not Supported</string>
|
||||
<string name="msg_device_not_supported">Unfortunately, your device is not supported at the moment. We are sorry for the inconvenience.\n\nSupported CPU ABIs: aarch64 and armeabi-v7a</string>
|
||||
|
||||
@@ -66,16 +67,16 @@
|
||||
<string name="quick_run_debug">Quick run</string>
|
||||
<string name="msg_sync_needed">Gradle files have changed. Please rebuild your project to sync dependencies and configurations.</string>
|
||||
<string name="preparing">Preparing</string>
|
||||
<string name="preparing_first">Preparing. First build may take up to 10–15 minutes!</string>
|
||||
<string name="preparing_first">Preparing. First build may take up to 10–15 minutes!</string>
|
||||
<string name="msg_installing_gradlew">Gradle Wrapper is not available!\nInstalling default one. Gradle v7.4 will be downloaded if necessary.</string>
|
||||
<string name="msg_getting_daemom_status">Getting Daemon status, please wait…</string>
|
||||
<string name="msg_getting_daemom_status">Getting Daemon status, please wait…</string>
|
||||
<string name="gradle_daemon_status">Gradle daemon status</string>
|
||||
<string name="title_install_apks">Install APK(s)</string>
|
||||
<string name="title_clear_output">Clear output</string>
|
||||
<string name="run">Run</string>
|
||||
<string name="gradle">Gradle</string>
|
||||
<string name="title_first_build">First Build</string>
|
||||
<string name="msg_first_build">This is the first time build after you installed AndroidIDE. First build usually takes time as Gradle downloads all dependencies and plugins. This process may take about 10–15 minutes. But this totally depends on your network connection.\n\nPlease be patient …</string>
|
||||
<string name="msg_first_build">This is the first time build after you installed AndroidIDE. First build usually takes time as Gradle downloads all dependencies and plugins. This process may take about 10–15 minutes. But this totally depends on your network connection.\n\nPlease be patient …</string>
|
||||
|
||||
<!-- Project -->
|
||||
<string name="create_project">Create project</string>
|
||||
@@ -107,6 +108,13 @@
|
||||
<string name="template_description_libgdx">LibGDX game project set up to render an image as an example.</string>
|
||||
<string name="template_compose">Jetpack Compose</string>
|
||||
<string name="template_description_compose">Basic Jetpack Compose hello world project.</string>
|
||||
<string name="template_navigation_tabs">Bottom Navigation Activity</string>
|
||||
<string name="template_navigation_tabs_description">Creates a new activity with bottom navigation</string>
|
||||
<string name="template_tabs">Tabbed Activity</string>
|
||||
<string name="template_tabs_description">Creates a new blank activity with tabs</string>
|
||||
<string name="template_fragment_and_viewmodel">Fragment + ViewModel</string>
|
||||
<string name="template_cpp">Native C++</string>
|
||||
<string name="template_cpp_description">Creates a new project with an Empty Activity configured to use JNI</string>
|
||||
|
||||
<!-- Files -->
|
||||
<string name="save">Save</string>
|
||||
@@ -119,7 +127,7 @@
|
||||
<string name="msg_find_project_filter">Separated by \'|\'</string>
|
||||
<string name="msg_empty_search_query">Please enter text</string>
|
||||
<string name="msg_select_search_modules">Select modules to search</string>
|
||||
<string name="msg_searching_project">Finding in project, please wait…</string>
|
||||
<string name="msg_searching_project">Finding in project, please wait…</string>
|
||||
<string name="view_search_results">Search results</string>
|
||||
<string name="copying_files">Copying files</string>
|
||||
<string name="writing_files">Writing files</string>
|
||||
@@ -179,6 +187,7 @@
|
||||
<!-- Code Editor -->
|
||||
<string name="undo">Undo</string>
|
||||
<string name="redo">Redo</string>
|
||||
|
||||
<item name="copy" type="string" tools:override="true">Copy</item>
|
||||
<item name="text_to_search" type="string">Text to search</item>
|
||||
|
||||
@@ -215,7 +224,6 @@
|
||||
<string name="msg_editor_font_size">Please choose default font size of editor :</string>
|
||||
<string name="msg_clear_cache">This will delete caches directory created by Gradle. If you delete it, the next build may take a bit longer than normal as Gradle will download required files again.\nIMPORTANT: This will also delete AAPT2. You will need to reinstall it otherwise you\'ll end up with a build failure.\n\nAre you sure you want to delete caches?</string>
|
||||
|
||||
|
||||
<!-- Error Messages used while Logging -->
|
||||
<string name="err_init_sdkinfo">Unable to initialize SDK Info</string>
|
||||
<string name="err_cannot_preview_layout">Unable to preview layout</string>
|
||||
@@ -264,7 +272,7 @@
|
||||
<string name="msg_bootstrap_installation_error">Bootstrap installation failed with the following exception.</string>
|
||||
<string name="title_translations">Translations</string>
|
||||
<string name="title_compiler_module_install">Installing compiler module</string>
|
||||
<string name="msg_compiler_module_install">Compiler module is being installed, please wait…</string>
|
||||
<string name="msg_compiler_module_install">Compiler module is being installed, please wait…</string>
|
||||
<string name="msg_compiler_module_install_failed">Compiler module installation failed. The error was:\n%s</string>
|
||||
<string name="msg_compiler_module_installed">Compiler module installed successfully!</string>
|
||||
<string name="action_expand_selection">Expand selection</string>
|
||||
@@ -278,7 +286,6 @@
|
||||
<string name="idepref_java_matchLower_summary">If enabled, then typing a lower case or upper case letters will suggest class names as well as scope members.</string>
|
||||
<string name="idepref_editor_ligatures_title">Font ligatures</string>
|
||||
<string name="idepref_editor_ligatures_summary">Enable/disable font ligatures</string>
|
||||
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="msg_apk_install_intent_failed">Unable to start intent for installing APK</string>
|
||||
@@ -301,12 +308,12 @@
|
||||
<string name="idepref_visiblePassword_summary">Use for visible password input type flag in editor. This makes sure that no suggestions are proposed by soft keyboard.</string>
|
||||
<string name="previous">Previous</string>
|
||||
<string name="msg_replacing">Replacing…</string>
|
||||
|
||||
<string name="title_gradle_service_notification_ticker">Gradle build service started</string>
|
||||
<string name="title_gradle_service_notification">Gradle build service</string>
|
||||
<string name="msg_gradle_service_notification">AndroidIDE\'s Gradle build service is running in the background.</string>
|
||||
|
||||
<string name="title_cancel_build">Cancel build</string>
|
||||
<string name="title_warning">Warning</string>
|
||||
<string name="msg_ndk_currently_unsupported">NDK is currently not officially supported. This template works only after you setup NDK</string>
|
||||
<string name="msg_initializing_project">Initializing project</string>
|
||||
<string name="msg_project_initialized">Project initialized</string>
|
||||
<string name="msg_project_initialization_failed">Project initialization failed</string>
|
||||
@@ -314,19 +321,19 @@
|
||||
<string name="msg_running_task">Running task: \'%1$s\'</string>
|
||||
<string name="msg_replacement">Replacement</string>
|
||||
<string name="title_sync_project">Sync project</string>
|
||||
|
||||
<string name="wizard_error_name_empty">Name cannot be empty.</string>
|
||||
<string name="wizard_error_name_illegal">Name cannot contain illegal characters</string>
|
||||
<string name="wizard_save_location">Save location</string>
|
||||
<string name="wizard_language">Project Language</string>
|
||||
<string name="wizard_loading">Templates loading…</string>
|
||||
<string name="wizard_toolchain">C++ Standard</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="exit">Exit</string>
|
||||
|
||||
<string name="idepref_title_tpFix">JDK 11 tag pointers fix</string>
|
||||
<string name="idepref_msg_tpFix">Set LD_PRELOAD to libhook.so to fix tag pointers issue for JDK 11 in Android 11 [DEPRECATED - Prefer using JDK 17].</string>
|
||||
<string name="idepref_title_customGradleInstallation">Custom Gradle installation</string>
|
||||
<string name="idepref_msg_customGradleInstallation">Specify a custom Gradle installation to use for build. This OVERRIDES the version specified in gradle-wrapper.properties.</string>
|
||||
<string name="msg_gradle_installation_path">Gradle installation path</string>
|
||||
<string name="msg_gradle_installation_input_help">Leave empty to use Gradle wrapper.</string>
|
||||
|
||||
</resources>
|
||||