How to launch another app in Android

98 views
Skip to first unread message

Bryan Buchanan

unread,
Dec 20, 2014, 12:43:25 AM12/20/14
to codenameone...@googlegroups.com
I'm using native code which Chen helped with in a previous post, and it looks like it works. The developers of the API have provided an emulator which runs on an Android device, which simulates a payment terminal. When I call the Intent from my app it aborts as you can see in this screen shot from the Android monitor:

When I run one of the sample programs provided with the API toolkit, I notice straight after it starts, it also starts the emulator:


I'm wondering if I need to do this from my CN1 app, or should it automagically happen because the emulator services the intent name I'm wanting to use ?

Thanks.

Shai Almog

unread,
Dec 20, 2014, 1:45:25 AM12/20/14
to codenameone...@googlegroups.com
It looks like you are activating an activity that isn't there.

Bryan Buchanan

unread,
Dec 20, 2014, 3:47:40 AM12/20/14
to codenameone...@googlegroups.com
That's the problem, it should be there. These are the instructions for loading the simulator and sample apps for the payment terminal:

Please ensure your current working directory is set to the root of the Aevi SDK installation folder

  1. To install the Aevi Simulator

     adb install android/simulator/Simulator-1.2.3.apk
    
  2. To optionally install the Aevi Sample app:

     adb install samples/AeviSample-1.2.3.apk
    
  3. To optionally install the BarPos Example app:

     adb install samples/BarPosExample-1.2.3.apk
    
  4. To optionally install the To The Movies app:

     adb install samples/ToTheMovies-1.2.3.apk
    
  5. To optionally install the To The Movies Classic app:

     adb install samples/ToTheMoviesClassic-1.2.3.apk
    

    I have done all this, and the BarPosExample, which is the dump I sent, runs and activates the simulator app when a payment intent is activated. As far as I can see, the app doesn't actually do anything to load the emulator, so I assume that the Android runtime knows somehow when intent "X" is called what app to launch. So, I'm wondering why this isn't being done from my app, when I'm calling the intent as per the example.

Bryan Buchanan

unread,
Dec 20, 2014, 4:06:39 AM12/20/14
to codenameone...@googlegroups.com
The manifest for the Bar sample app is:

<?xml version="1.0" encoding="utf-8"?>
          package="com.aevi.barposexample"
          android:versionCode="13"
          android:versionName="1.2.3">

  <uses-sdk
      android:minSdkVersion="15"
      android:targetSdkVersion="15"/>

  <uses-permission android:name="com.aevi.permission.CONFIGURATION"/>
  <uses-permission android:name="com.aevi.permission.PAYMENT_REQUEST"/>

  <application
      android:name="BarPosApplication"
      android:icon="@drawable/wincor_icon"
      android:label="@string/app_name"
      android:theme="@style/AppTheme">
    <activity
        android:name=".TableSelectionActivity"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
    <activity
        android:name=".ItemSelectionActivity"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
        />
    <activity
        android:name=".PaymentActivity"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
        />
  </application>

  <meta-data
      android:name="application-type"
      android:value="payment"/>


</manifest>


My properties file has this line:

codename1.android.xpermissions=<uses-permission android\:name\="com.aevi.permission.CONFIGURATION" /><uses-permission android\:name\="com.aevi.permission.PAYMENT_REQUEST" />


so AFAICT it should be working. I tried to unzip the apk of my app, but the AndroidManifest.xml looks to be encrypted, so I cannot check.

Bryan Buchanan

unread,
Dec 20, 2014, 4:27:49 AM12/20/14
to codenameone...@googlegroups.com
Further to this, checking on the actual device, my test app does NOT list the two permissions that the Bar app sets, even though I thought I was setting them using codename1.android.xpermissions.

Shai Almog

unread,
Dec 20, 2014, 11:09:25 AM12/20/14
to codenameone...@googlegroups.com
The permissions are there in the manifest but the UI doesn't always reflect the full permissions.

Did you try asking the Aevi SDK why your code doesn't work?

Bryan Buchanan

unread,
Dec 20, 2014, 11:56:06 AM12/20/14
to codenameone...@googlegroups.com


On Sunday, December 21, 2014 2:09:25 AM UTC+10, Shai Almog wrote:
The permissions are there in the manifest but the UI doesn't always reflect the full permissions.

Why don't they show when on the device I go to Settings => Apps => my app to see the permissions the app has. 

Did you try asking the Aevi SDK why your code doesn't work?

Not yet, I'm not sure it is their problem. It is an Android permissions problem from the look of it. 

Bryan Buchanan

unread,
Dec 20, 2014, 3:04:27 PM12/20/14
to codenameone...@googlegroups.com
I created a brand new CN1 project, and the only things changed were in codenameone_settings.properties:

1. adding Android keystore stuff

2. the extra permissions:
codename1.android.xpermissions=<uses-permission android\:name\="com.aevi.permission.CONFIGURATION" /><uses-permission android\:name\="com.aevi.permission.PAYMENT_REQUEST" />

When I loaded the app on a device, the app properties are:



The example BarPos app has these permissions:

which is the problem. Even though I am asking for the permissions, they don't seem to be getting set.

Bryan Buchanan

unread,
Dec 20, 2014, 6:03:53 PM12/20/14
to codenameone...@googlegroups.com
one other thing that is in the manifest of the BarPos example app is:

  <meta-data
      android:name="application-type"
      android:value="payment"/>


maybe this needs to be set for the permissions to "take". There doesn't appear to be a CN1 build option to add this.

 The full manifest for the BarPos app is:

Shai Almog

unread,
Dec 21, 2014, 12:32:16 AM12/21/14
to codenameone...@googlegroups.com
You can add that meta data to the permissions section.
Looking at the manifest above I thought it was something from your application. Send a build with include sources and take a look at the manifest file that is generated.

Bryan Buchanan

unread,
Dec 21, 2014, 2:55:43 AM12/21/14
to codenameone...@googlegroups.com
That include source is pretty neat. Never used it before.

This is the manifest generated:
<?xml version="1.0" encoding="utf-8"?>
      package="com.mycompany.myapp"
      android:versionCode="120"
      android:versionName="1.2"
      android:minSdkVersion="7"
      android:installLocation="auto">
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21"  />
    <supports-screens android:smallScreens="true"
          android:normalScreens="true"
          android:largeScreens="true"
          android:xlargeScreens="true"
          android:anyDensity="true" />
    <application android:label="CodenameOnePermsTest"  android:icon="@drawable/icon">
        <activity android:name="MyApplicationStub"
                  android:theme="@style/CustomTheme"
                  android:configChanges="orientation|keyboardHidden|screenSize"
                  android:launchMode="singleTop"
                  android:label="CodenameOnePermsTest">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
      </application>
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    <uses-feature android:name="android.hardware.telephony" android:required="false" />
    <uses-permission android:name="android.permission.INTERNET" android:required="false" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="false" />
  </manifest>


The values for codename1.android.xpermissions seem to have been ignored. This is my codename1.android.xpermissions (with the keystore stuff blanked)

#Sun Dec 21 17:47:35 EST 2014
codename1.ios.appid=Q5GHSKAL2F.com.mycompany.myapp
codename1.ios.release.provision=
codename1.arg.rim.obfuscation=false
codename1.j2me.nativeTheme=nbproject/nativej2me.res
codename1.arg.ios.project_type=ios
codename1.arg.ios.interface_orientation=UIInterfaceOrientationPortrait\:UIInterfaceOrientationPortraitUpsideDown\:UIInterfaceOrientationLandscapeLeft\:UIInterfaceOrientationLandscapeRight
codename1.displayName=CodenameOnePermsTest
guiResource=theme.res
codename1.android.keystoreAlias=XXXXXXX
codename1.ios.release.certificate=
codename1.android.keystorePassword=XXXXXXXX
codename1.ios.provision=
codename1.arg.android.release=true
codename1.arg.ios.dsym=false
package=generated
codename1.arg.ios.statusbar_hidden=false
codename1.languageLevel=5
codename1.android.keystore=XXXXXXX
mainForm=Main
codename1.vendor=CodenameOne
codename1.arg.win.ver=8
codename1.ios.certificatePassword=
codename1.arg.zooz.sandbox=false
codename1.ios.debug.certificatePassword=
codename1.mainName=MyApplication
codename1.ios.release.certificatePassword=
codename1.arg.ios.prerendered_icon=false
codename1.arg.vserv.scaleMode=false
codename1.ios.debug.certificate=
libVersion=80
codename1.arg.ios.application_exits=false
codename1.android.xpermissions=<meta-data android\:name\="application-type" android\:value\="payment"/><uses-permission android\:name\="com.aevi.permission.CONFIGURATION" /><uses-permission android\:name\="com.aevi.permission.PAYMENT_REQUEST" />
codename1.secondaryTitle=CodenameOnePermsTest
codename1.description=
codename1.ios.debug.provision=
baseClass=src/generated/StateMachineBase.java
codename1.arg.build.incSources=1
codename1.arg.j2me.nativeThemeConst=0
codename1.rim.certificatePassword=
codename1.version=1.2
codename1.ios.certificate=
codename1.icon=icon.png
codename1.rim.signtoolCsk=
codename1.arg.android.debug=false
codename1.arg.vserv.transition=20000
codename1.rim.signtoolDb=
userClass=src/userclasses/StateMachine.java
codename1.arg.ios.includePush=false
codename1.packageName=com.mycompany.myapp

Bryan Buchanan

unread,
Dec 21, 2014, 3:04:59 AM12/21/14
to codenameone...@googlegroups.com
Solved !  Just noticed the value in codenameone_settings.properties should be "codename1.arg.android.xpermissions" and not "codename1.android.xpermissions"

The test permissions app shows the settings, so now I can see if the payment app works.

Thanks for your help.

Bryan Buchanan

unread,
Dec 21, 2014, 4:07:00 AM12/21/14
to codenameone...@googlegroups.com
As previous post mentioned, I got a bit further. The manifest for my CN1 Payment test prog is now correct:

<?xml version="1.0" encoding="utf-8"?>
      package="com.webbtide.albert"
      android:versionCode="100"
      android:versionName="1.0"
      android:minSdkVersion="7"
      android:installLocation="auto">
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21"  />
    <supports-screens android:smallScreens="true"
          android:normalScreens="true"
          android:largeScreens="true"
          android:xlargeScreens="true"
          android:anyDensity="true" />
    <application android:label="AlbertDemo"  android:icon="@drawable/icon">
        <activity android:name="AlbertDemoStub"
                  android:theme="@style/CustomTheme"
                  android:configChanges="orientation|keyboardHidden|screenSize"
                  android:launchMode="singleTop"
                  android:label="AlbertDemo">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
      </application>
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    <uses-feature android:name="android.hardware.telephony" android:required="false" />
    <uses-permission android:name="android.permission.INTERNET" android:required="false" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:required="false" />
  <meta-data android:name="application-type" android:value="payment"/>
<uses-permission android:name="com.aevi.permission.CONFIGURATION" />
<uses-permission android:name="com.aevi.permission.PAYMENT_REQUEST" /></manifest>


But it looks like there is an obfuscation problem. The debug log from running the supplied BarPosExample:

12-21 18:44:57.211: I/ActivityManager(154): START {cmp=com.aevi.barposexample/.PaymentActivity (has extras)} from pid 2262
12-21 18:44:57.271: I/SystemProperties(154): get key=ro.build.characteristics,def=none
12-21 18:44:57.271: I/SystemProperties(154): get key=ro.screen.layout
12-21 18:44:57.271: I/WindowManager(154): SCREENLAYOUT_SIZE (1:small, 2:normal, 3:large, 4:xlarge) 3
12-21 18:44:57.311: I/SystemProperties(2262): get key=viewancestor.profile_rendering,def=false
12-21 18:44:57.311: I/SystemProperties(2262): get key=hwui.disable_vsync,def=false
12-21 18:44:57.351: D/Settings(337): getAllInstallLangId().length43
12-21 18:44:57.381: D/gralloc(92): alloc_buffer: Successfully allocated 0x244000 bytes, mIonFd=27, SharedFd=28
12-21 18:44:57.391: D/gralloc(2262): map_buffer: Successfully mapped 0x244000 bytes at address 0x63f32000, SharedFd=57, map_count = 3
12-21 18:44:57.391: I/ActivityManager(154): Displayed com.aevi.barposexample/.PaymentActivity: +122ms
12-21 18:44:57.401: D/OpenGLRenderer(2262): Flushing caches (mode 0)
12-21 18:44:57.401: D/gralloc(2262): unmap_buffer: Successfully unmapped 0x244000 bytes at address 0x64176000, SharedFd=58, map_count = 2
12-21 18:44:57.401: D/gralloc(2262): unmap_buffer: Successfully unmapped 0x244000 bytes at address 0x63b31000, SharedFd=56, map_count = 1
12-21 18:44:57.401: D/gralloc(92): free_buffer: Freeing 0x244000 bytes, mIonFd=27 SharedFd=19
12-21 18:44:57.401: D/gralloc(92): unmap_buffer: Successfully unmapped 0x244000 bytes at address 0x4a146000, SharedFd=19, map_count = 5
12-21 18:44:57.631: D/gralloc(92): free_buffer: Freeing 0x244000 bytes, mIonFd=27 SharedFd=32
12-21 18:44:57.631: D/gralloc(92): unmap_buffer: Successfully unmapped 0x244000 bytes at address 0x4a747000, SharedFd=32, map_count = 4
12-21 18:44:58.131: I/SystemProperties(154): get key=events.cpu
12-21 18:44:58.711: D/gralloc(92): alloc_buffer: Successfully allocated 0x244000 bytes, mIonFd=27, SharedFd=19
12-21 18:44:58.721: D/gralloc(2262): map_buffer: Successfully mapped 0x244000 bytes at address 0x63b31000, SharedFd=56, map_count = 2
12-21 18:44:58.871: I/ActivityManager(154): START {act=com.aevi.payment.REQUEST cmp=com.aevi.simulator/.PaymentRequestActivity (has extras)} from pid 2262


the last line shows starting the payment emulator. When I run my program:

12-21 18:46:56.581: E/AndroidRuntime(2343): FATAL EXCEPTION: Thread-268
12-21 18:46:56.581: E/AndroidRuntime(2343): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.aevi.a.REQUEST (has extras) }
12-21 18:46:56.581: E/AndroidRuntime(2343): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1512)
12-21 18:46:56.581: E/AndroidRuntime(2343): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1384)
12-21 18:46:56.581: E/AndroidRuntime(2343): at android.app.Activity.startActivityForResult(Activity.java:3190)
12-21 18:46:56.581: E/AndroidRuntime(2343): at com.codename1.impl.android.CodenameOneActivity.startActivityForResult(CodenameOneActivity.java:511)
12-21 18:46:56.581: E/AndroidRuntime(2343): at com.codename1.impl.android.e.a(AndroidNativeUtil.java:139)
12-21 18:46:56.581: E/AndroidRuntime(2343): at com.webbtide.albert.c.a(NativeCallsImpl.java:46)
12-21 18:46:56.581: E/AndroidRuntime(2343): at com.webbtide.albert.d.a(NativeCallsStub.java:13)
12-21 18:46:56.581: E/AndroidRuntime(2343): at b.a$1.run(StateMachine.java:54)


the activity that is invoked is "com.aevi.a.REQUEST" and not "com.aevi.payment.REQUEST"

All I've done in my native code is copy the example's code:

        PaymentRequest payment = new PaymentRequest(new BigDecimal(param));
        payment.setCurrency(Currency.getInstance("AUD"));

        Intent intent = payment.createIntent();
        Log.v("AlbertDemo", intent.toString());
        
        IntentResultListener listener = new IntentResultListener() {
            
            public void onActivityResult(int requestCode, int resultCode, Intent data) {

                // Obtain the transaction result from the returned data.
                TransactionResult transresult = TransactionResult.fromIntent(data);
                // Check whether the transaction was successful
                if (transresult.getTransactionStatus() == TransactionStatus.APPROVED) {
                    // transaction successful
                    result = NativeCalls.OK;
                } else {
                    // transaction failed
                    result = NativeCalls.ERROR;
                }
            }
            
        };
        
        AndroidNativeUtil.startActivityForResult(intent, listener);

The output of the Log.v above is:
12-21 18:46:56.541: V/AlbertDemo(2343): Intent { act=com.aevi.a.REQUEST (has extras) }

How can I stop those classes being obfuscated ?

Chen Fishbein

unread,
Dec 21, 2014, 7:23:59 AM12/21/14
to codenameone...@googlegroups.com
Try:
android.enableProguard=false

Bryan Buchanan

unread,
Dec 21, 2014, 2:41:22 PM12/21/14
to codenameone...@googlegroups.com
Thanks Chen - you're a genius !  Demo CN1 program calls the simulator, so it looks like all is good. Still need to do a bit more testing, but I think we're on our way. Many thanks.

On Sunday, December 21, 2014 10:23:59 PM UTC+10, Chen Fishbein wrote:
Try:
android.enableProguard=false

Bryan Buchanan

unread,
Dec 21, 2014, 5:27:54 PM12/21/14
to codenameone...@googlegroups.com
For anyone else who might need to call a custom intent on Android, this is a summary of what probably needs to be done:


2. if you need external jars sent to the server as part of the build, put them in [project]/native/android

3. if you need to add permissions or other info to the Android manifest, edit codenameone_settings.properties and add the line

codename1.arg.android.xpermissions=<uses-permission android\:name\="com.aevi.permission.PAYMENT_REQUEST" />

if you have a number of options, just append to this line (maybe with a \n between them for readability in the generated manifest)

4. it is quite likely you will NOT want the code obfuscated because when you invoke the intent you want the un-obfuscated name, so add

codename1.arg.android.enableProguard=false

to codenameone_settings.properties

5. Properties -> Premium Features -> Include Source => check this so you can download the source and inspect the created manifest.

After that, should all work.

Reply all
Reply to author
Forward
0 new messages