Is LiveCode for Android ready for prime time?

The place to discuss anything and everything about running your LiveCode on Android

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

BarrySumpter
Posts: 1201
Joined: Sun Apr 24, 2011 2:17 am

Re: Is LiveCode for Android ready for prime time?

Post by BarrySumpter » Fri Aug 26, 2011 6:18 am

I'm absolutely sure the Orientation was me not understanding anything about
how Android Orientation worked
how LiveCode handled Android Orientation
And all the variations on how each device handled Android Orientation.

I remember something about not having spaces between the mobileAllowedOrientations() values.

On Page 19 of the Android Release Notes from LC v4.6.3 1445,
is a section covering Orientation handling.

I get it now.
But have to admit it was overwhelming at the time.
Especially, trying to learn all the ins n outs of LiveCode scripting and testing plaforms etc. as well.

----
"...4 out of 5 LiveCode developers considered iOS more important to their business model than Android..."
Ah, righto! I get where RunRev is coming from now.
I'll do me best to accept it and move on.
...the user is supposed to be in control...
Not with my propriatary apps. And not my users.
They are there to do a job. Not play with orientation.
My dataEntry cards and dataReport cards are specificly designed for landascape.
I guess I could start in landscape and not allow another orientation.
But that kind of defeats the purpose of using a phone.
I'll have to put up with it until RunRev sort it out or RunRev sorts out Externals.
Last edited by BarrySumpter on Sat Aug 27, 2011 9:03 am, edited 2 times in total.
All my best,
Barry G. Sumpter

Deving on WinXP sp3-32 bit. LC 5.5 Professional Build 1477
Android/iOS/Server Add Ons. OmegaBundle 2011 value ROCKS!
2 HTC HD2 Latest DorimanX Roms
Might have to reconsider LiveCode iOS Developer Program.

Gene
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 75
Joined: Wed Mar 09, 2011 6:48 pm
Location: Northern California

Re: Is LiveCode for Android ready for prime time?

Post by Gene » Fri Aug 26, 2011 6:31 pm

jacque wrote:You're right there is no support for externals yet, RR is working on that. The goal is parity between both mobile products. But they did a survey (see their latest blog post) that showed 4 out of 5 LiveCode developers considered iOS more important to their business model than Android, so of course that's where their efforts are focused for now.
I very much understand the need for RunRev to develop for the market. That's what I would do. However, I'm part of the twenty percent in the survey, and I have to say that I've been in a holding pattern with an Android personal license for some time now, waiting for RunRev to mature on the Android side before investing the additional $400.00 to make a committment. There was a time when I would have thrown that kind of money for software at the wall just to see what stuck, but not these days. So, just like RunRev, I'm forced to vote with my wallet. Sigh.

shawnb
Posts: 11
Joined: Mon Jul 04, 2011 2:23 am

Re: Is LiveCode for Android ready for prime time?

Post by shawnb » Sat Aug 27, 2011 3:34 am

With all of the news about Android developers being in DEMAND and surpassing iOS developers in 2012, you'd think that RR would get Android working like it should. Like others I'm still in a holding pattern and haven't departed with my lovely cash! Once LC for Android is up to snuff I'll gladly pay the big bucks for a license, until then I'll continue learning Java / Eclipse. It's free.
Until LC for Android can create the same type of applications that I can create with Java or Lua, I'll be using Java and Lua. I'd love to use LC, but LC for Android is not ready for prime time.

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7258
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Is LiveCode for Android ready for prime time?

Post by jacque » Sat Aug 27, 2011 4:48 am

Aside from GPS, what do you need implemented?
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

BarrySumpter
Posts: 1201
Joined: Sun Apr 24, 2011 2:17 am

Re: Is LiveCode for Android ready for prime time?

Post by BarrySumpter » Sat Aug 27, 2011 5:28 am

Aside from GPS, what do you need implemented?
Certainly appreciate all that RunRev have supplied so far
and all the support and the incredible value in the OmegaBundle,
et all.

1. Externals (if I understand them properly so I can call dlls and interface with other apps without delving into c#)
----- Externals may answer most of the following:
2. Forced Orientation at call - if n when possible
3. inFrame/on card Video control
4. Access to Android Contacts, Calendar, SMS etc.
5. LiveCode (web) Player for Android
6. Numeric Keyboard
7. More detailed doco
May not be possible:
8. An iOS app that convinces all Apple users and their developers into moving to Android.

hth
Keeping me fingers crossed but not holding me breath.
Last edited by BarrySumpter on Sat Aug 27, 2011 9:04 am, edited 2 times in total.
All my best,
Barry G. Sumpter

Deving on WinXP sp3-32 bit. LC 5.5 Professional Build 1477
Android/iOS/Server Add Ons. OmegaBundle 2011 value ROCKS!
2 HTC HD2 Latest DorimanX Roms
Might have to reconsider LiveCode iOS Developer Program.

BarrySumpter
Posts: 1201
Joined: Sun Apr 24, 2011 2:17 am

Re: Is LiveCode for Android ready for prime time?

Post by BarrySumpter » Sat Aug 27, 2011 5:35 am

shawnb wrote:With all of the news about Android developers being in DEMAND and surpassing iOS developers in 2012, you'd think that RR would get Android working like it should. ..., until then I'll continue learning Java / Eclipse. It's free.
Yep, that's why I chose Android.
I had warning bells going of in me head when limiting the questions to current LiveCoders.

--
In your opinion, shawnb, is Java and Eclipse easy to learn?
I had a quick look at Java and LiveCode seemed to me far easier.
Knowing nothing about either at the time.
All my best,
Barry G. Sumpter

Deving on WinXP sp3-32 bit. LC 5.5 Professional Build 1477
Android/iOS/Server Add Ons. OmegaBundle 2011 value ROCKS!
2 HTC HD2 Latest DorimanX Roms
Might have to reconsider LiveCode iOS Developer Program.

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7258
Joined: Sat Apr 08, 2006 8:31 pm
Location: Minneapolis MN
Contact:

Re: Is LiveCode for Android ready for prime time?

Post by jacque » Sat Aug 27, 2011 6:43 am

BarrySumpter wrote:
1. Externals (if I understand them properly so I can call dlls and interface with other apps without delving into c#)
----- Externals may answer most of the following:
2. Forced Orientation at call - if n when possible
3. inFrame/on card Video control
4. Access to Android Contacts, Calendar, SMS etc.
5. LiveCode (web) Player for Android
6. Numeric Keyboard
7. More detailed doco
May not be possible:
8. An iOS app that convinces all Apple users and their developers into moving to Android.

hth
Keeping me fingers crossed but not holding me breath.
Quick comments:

1. That's not what external support means. LiveCode externals must be written specifically for the LC engine using the RR API. You can't directly run DLLs in LiveCode on any platform. I suppose you could write a LiveCode external that would load an existing DLL and serve as an intermediary, but it would only work with that particular DLL, and you'd still need to know C++ or similar.

2. Forced orientation isn't supported on either iOS or Android, so they are in parity here. I don't think the HIG for either OS likes it either. I have seen one app that does show a dialog in landscape regardless of how I'm holding the device and it irritates me. The workaround if you absolutely must do it is to simply rotate a snapshot of the screen image 90 degrees on the card. I won't use your app if you do that though. :P

3. Video playback is limited to full screen, landscape on both iOS and Android, so they are in parity here.

4. Contacts, direct Calendar access, and SMS are not available on either OS yet, so parity here.

5. Web player is on iOS, so that needs to catch up. But in all the Android apps I use, typically they all call out to the user's browser for URL linking. It's rare to see an embedded browser. URL linking is supported in Android.

6. Numeric keyboard is already supported in Android.

7. Docs -- they have mostly been integrated into the dictionary now. The release notes are an overview.

8. I try to remain neutral. I use both an iPad and an Android tablet.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

shawnb
Posts: 11
Joined: Mon Jul 04, 2011 2:23 am

Re: Is LiveCode for Android ready for prime time?

Post by shawnb » Sat Aug 27, 2011 5:50 pm

BarrySumpter wrote:
shawnb wrote:With all of the news about Android developers being in DEMAND and surpassing iOS developers in 2012, you'd think that RR would get Android working like it should. ..., until then I'll continue learning Java / Eclipse. It's free.
Yep, that's why I chose Android.
I had warning bells going of in me head when limiting the questions to current LiveCoders.

--
In your opinion, shawnb, is Java and Eclipse easy to learn?
I had a quick look at Java and LiveCode seemed to me far easier.
Knowing nothing about either at the time.
For me Java / Eclipse is pretty tough. The code below is from one file in the demo ContactsManager, this is to add a contact. Until LiveCode for Android is a suitable alternative to Java though, I'll be learning Java. One thing that I see that's really useful in Java / Eclipse is to develop once and deploy on multiple Android devices without regard for the screen size or resolution. Until LiveCode for Android supports that, location based app development, access to contacts, sms, etc ... many social type apps can't be developed with LiveCode for Android. Titanium is another platform for developing Android apps and they have a demo called 'kitchen sink', I think we need something like that for LiveCode and LiveCode for Android.




Code: Select all

/*
 * Copyright (C) 2009 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.example.android.contactmanager;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

import java.util.ArrayList;
import java.util.Iterator;

public final class ContactAdder extends Activity implements OnAccountsUpdateListener
{
    public static final String TAG = "ContactsAdder";
    public static final String ACCOUNT_NAME =
            "com.example.android.contactmanager.ContactsAdder.ACCOUNT_NAME";
    public static final String ACCOUNT_TYPE =
            "com.example.android.contactmanager.ContactsAdder.ACCOUNT_TYPE";

    private ArrayList<AccountData> mAccounts;
    private AccountAdapter mAccountAdapter;
    private Spinner mAccountSpinner;
    private EditText mContactEmailEditText;
    private ArrayList<Integer> mContactEmailTypes;
    private Spinner mContactEmailTypeSpinner;
    private EditText mContactNameEditText;
    private EditText mContactPhoneEditText;
    private ArrayList<Integer> mContactPhoneTypes;
    private Spinner mContactPhoneTypeSpinner;
    private Button mContactSaveButton;
    private AccountData mSelectedAccount;

    /**
     * Called when the activity is first created. Responsible for initializing the UI.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        Log.v(TAG, "Activity State: onCreate()");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contact_adder);

        // Obtain handles to UI objects
        mAccountSpinner = (Spinner) findViewById(R.id.accountSpinner);
        mContactNameEditText = (EditText) findViewById(R.id.contactNameEditText);
        mContactPhoneEditText = (EditText) findViewById(R.id.contactPhoneEditText);
        mContactEmailEditText = (EditText) findViewById(R.id.contactEmailEditText);
        mContactPhoneTypeSpinner = (Spinner) findViewById(R.id.contactPhoneTypeSpinner);
        mContactEmailTypeSpinner = (Spinner) findViewById(R.id.contactEmailTypeSpinner);
        mContactSaveButton = (Button) findViewById(R.id.contactSaveButton);

        // Prepare list of supported account types
        // Note: Other types are available in ContactsContract.CommonDataKinds
        //       Also, be aware that type IDs differ between Phone and Email, and MUST be computed
        //       separately.
        mContactPhoneTypes = new ArrayList<Integer>();
        mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_HOME);
        mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
        mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
        mContactPhoneTypes.add(ContactsContract.CommonDataKinds.Phone.TYPE_OTHER);
        mContactEmailTypes = new ArrayList<Integer>();
        mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_HOME);
        mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_WORK);
        mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_MOBILE);
        mContactEmailTypes.add(ContactsContract.CommonDataKinds.Email.TYPE_OTHER);

        // Prepare model for account spinner
        mAccounts = new ArrayList<AccountData>();
        mAccountAdapter = new AccountAdapter(this, mAccounts);
        mAccountSpinner.setAdapter(mAccountAdapter);

        // Populate list of account types for phone
        ArrayAdapter<String> adapter;
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        Iterator<Integer> iter;
        iter = mContactPhoneTypes.iterator();
        while (iter.hasNext()) {
            adapter.add(ContactsContract.CommonDataKinds.Phone.getTypeLabel(
                    this.getResources(),
                    iter.next(),
                    getString(R.string.undefinedTypeLabel)).toString());
        }
        mContactPhoneTypeSpinner.setAdapter(adapter);
        mContactPhoneTypeSpinner.setPrompt(getString(R.string.selectLabel));

        // Populate list of account types for email
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        iter = mContactEmailTypes.iterator();
        while (iter.hasNext()) {
            adapter.add(ContactsContract.CommonDataKinds.Email.getTypeLabel(
                    this.getResources(),
                    iter.next(),
                    getString(R.string.undefinedTypeLabel)).toString());
        }
        mContactEmailTypeSpinner.setAdapter(adapter);
        mContactEmailTypeSpinner.setPrompt(getString(R.string.selectLabel));

        // Prepare the system account manager. On registering the listener below, we also ask for
        // an initial callback to pre-populate the account list.
        AccountManager.get(this).addOnAccountsUpdatedListener(this, null, true);

        // Register handlers for UI elements
        mAccountSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int position, long i) {
                updateAccountSelection();
            }

            public void onNothingSelected(AdapterView<?> parent) {
                // We don't need to worry about nothing being selected, since Spinners don't allow
                // this.
            }
        });
        mContactSaveButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                onSaveButtonClicked();
            }
        });
    }

    /**
     * Actions for when the Save button is clicked. Creates a contact entry and terminates the
     * activity.
     */
    private void onSaveButtonClicked() {
        Log.v(TAG, "Save button clicked");
        createContactEntry();
        finish();
    }

    /**
     * Creates a contact entry from the current UI values in the account named by mSelectedAccount.
     */
    protected void createContactEntry() {
        // Get values from UI
        String name = mContactNameEditText.getText().toString();
        String phone = mContactPhoneEditText.getText().toString();
        String email = mContactEmailEditText.getText().toString();
        int phoneType = mContactPhoneTypes.get(
                mContactPhoneTypeSpinner.getSelectedItemPosition());
        int emailType = mContactEmailTypes.get(
                mContactEmailTypeSpinner.getSelectedItemPosition());;

        // Prepare contact creation request
        //
        // Note: We use RawContacts because this data must be associated with a particular account.
        //       The system will aggregate this with any other data for this contact and create a
        //       coresponding entry in the ContactsContract.Contacts provider for us.
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName())
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name)
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType)
                .build());
        ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE,
                        ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
                .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType)
                .build());

        // Ask the Contact provider to create a new contact
        Log.i(TAG,"Selected account: " + mSelectedAccount.getName() + " (" +
                mSelectedAccount.getType() + ")");
        Log.i(TAG,"Creating contact: " + name);
        try {
            getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (Exception e) {
            // Display warning
            Context ctx = getApplicationContext();
            CharSequence txt = getString(R.string.contactCreationFailure);
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(ctx, txt, duration);
            toast.show();

            // Log exception
            Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
        }
    }

    /**
     * Called when this activity is about to be destroyed by the system.
     */
    @Override
    public void onDestroy() {
        // Remove AccountManager callback
        AccountManager.get(this).removeOnAccountsUpdatedListener(this);
        super.onDestroy();
    }

    /**
     * Updates account list spinner when the list of Accounts on the system changes. Satisfies
     * OnAccountsUpdateListener implementation.
     */
    public void onAccountsUpdated(Account[] a) {
        Log.i(TAG, "Account list update detected");
        // Clear out any old data to prevent duplicates
        mAccounts.clear();

        // Get account data from system
        AuthenticatorDescription[] accountTypes = AccountManager.get(this).getAuthenticatorTypes();

        // Populate tables
        for (int i = 0; i < a.length; i++) {
            // The user may have multiple accounts with the same name, so we need to construct a
            // meaningful display name for each.
            String systemAccountType = a[i].type;
            AuthenticatorDescription ad = getAuthenticatorDescription(systemAccountType,
                    accountTypes);
            AccountData data = new AccountData(a[i].name, ad);
            mAccounts.add(data);
        }

        // Update the account spinner
        mAccountAdapter.notifyDataSetChanged();
    }

    /**
     * Obtain the AuthenticatorDescription for a given account type.
     * @param type The account type to locate.
     * @param dictionary An array of AuthenticatorDescriptions, as returned by AccountManager.
     * @return The description for the specified account type.
     */
    private static AuthenticatorDescription getAuthenticatorDescription(String type,
            AuthenticatorDescription[] dictionary) {
        for (int i = 0; i < dictionary.length; i++) {
            if (dictionary[i].type.equals(type)) {
                return dictionary[i];
            }
        }
        // No match found
        throw new RuntimeException("Unable to find matching authenticator");
    }

    /**
     * Update account selection. If NO_ACCOUNT is selected, then we prohibit inserting new contacts.
     */
    private void updateAccountSelection() {
        // Read current account selection
        mSelectedAccount = (AccountData) mAccountSpinner.getSelectedItem();
    }

    /**
     * A container class used to repreresent all known information about an account.
     */
    private class AccountData {
        private String mName;
        private String mType;
        private CharSequence mTypeLabel;
        private Drawable mIcon;

        /**
         * @param name The name of the account. This is usually the user's email address or
         *        username.
         * @param description The description for this account. This will be dictated by the
         *        type of account returned, and can be obtained from the system AccountManager.
         */
        public AccountData(String name, AuthenticatorDescription description) {
            mName = name;
            if (description != null) {
                mType = description.type;

                // The type string is stored in a resource, so we need to convert it into something
                // human readable.
                String packageName = description.packageName;
                PackageManager pm = getPackageManager();

                if (description.labelId != 0) {
                    mTypeLabel = pm.getText(packageName, description.labelId, null);
                    if (mTypeLabel == null) {
                        throw new IllegalArgumentException("LabelID provided, but label not found");
                    }
                } else {
                    mTypeLabel = "";
                }

                if (description.iconId != 0) {
                    mIcon = pm.getDrawable(packageName, description.iconId, null);
                    if (mIcon == null) {
                        throw new IllegalArgumentException("IconID provided, but drawable not " +
                                "found");
                    }
                } else {
                    mIcon = getResources().getDrawable(android.R.drawable.sym_def_app_icon);
                }
            }
        }

        public String getName() {
            return mName;
        }

        public String getType() {
            return mType;
        }

        public CharSequence getTypeLabel() {
            return mTypeLabel;
        }

        public Drawable getIcon() {
            return mIcon;
        }

        public String toString() {
            return mName;
        }
    }

    /**
     * Custom adapter used to display account icons and descriptions in the account spinner.
     */
    private class AccountAdapter extends ArrayAdapter<AccountData> {
        public AccountAdapter(Context context, ArrayList<AccountData> accountData) {
            super(context, android.R.layout.simple_spinner_item, accountData);
            setDropDownViewResource(R.layout.account_entry);
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            // Inflate a view template
            if (convertView == null) {
                LayoutInflater layoutInflater = getLayoutInflater();
                convertView = layoutInflater.inflate(R.layout.account_entry, parent, false);
            }
            TextView firstAccountLine = (TextView) convertView.findViewById(R.id.firstAccountLine);
            TextView secondAccountLine = (TextView) convertView.findViewById(R.id.secondAccountLine);
            ImageView accountIcon = (ImageView) convertView.findViewById(R.id.accountIcon);

            // Populate template
            AccountData data = getItem(position);
            firstAccountLine.setText(data.getName());
            secondAccountLine.setText(data.getTypeLabel());
            Drawable icon = data.getIcon();
            if (icon == null) {
                icon = getResources().getDrawable(android.R.drawable.ic_menu_search);
            }
            accountIcon.setImageDrawable(icon);
            return convertView;
        }
    }
}
Until LC for Android can create the same type of applications that I can create with Java or Lua, I'll be using Java and Lua. I'd love to use LC, but LC for Android is not ready for prime time.

Post Reply

Return to “Android Deployment”