How to build Different Android Apps using ant scripts - android

Hello i'm building a custom application.
PRE:
The app will be restricted to a limited amount of user. ( let's say 20 people )
The app should be unique per each user so each apk will refer to a user only.
Each app should have a different package name
So i was starting to think a building script that takes the user list and creates 20 apks ( one for each user ) and updates the strings.xml file with the custom modification needed per-user.
But i really don't know where to start. Is there a good way or a tutorial where i can refer to ?
Just to be clear i'd like to have a manifest like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="$pname"
android:versionCode="1"
android:versionName="1.0">
<application>...</application>
</manifest>
And then replace the $pname using ant.

Perhaps you are looking for the aapt command. It has an additional flag --rename-manifest-package. The help says
Rewrite the manifest so that its package name is the package name
given here. Relative class names (for example .Foo) will be
changed to absolute names with the old package so that the code
does not need to change.

I would be using 20 different semi-empty default activities (one per each of users) located in 20 different packages extending 1 real activity, like:
mypackage.user01.MyMainActivity extends mypackage.MyMainActivity;
mypackage.user02.MyMainActivity extends mypackage.MyMainActivity;
mypackage.user03.MyMainActivity extends mypackage.MyMainActivity;
...
mypackage.user20.MyMainActivity extends mypackage.MyMainActivity;
And then 20 different androidmanifests.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="mypackage.userXX">
<application
android:icon="#drawable/MyIcon"
android:label="#string/MyApplication"
>
<activity android:name=".MyActivity"
android:label="#string/MyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="mypackage.MyActivity"
android:label="#string/MyActivity"/>
<activity
android:name="mypackage.user01.MyActivity"
android:label="#string/MyActivity"/>
<!-- etc. till user20 -->
</application>
</manifest>
which will be copied using simple Ant copy tasks to real one - it's easy to implement, though a bit boring :)

It might be simpler if you store 20 codes in your app, and give one code to each customer. Then just give each customer the same application. The application changes its properties depending on what code was entered.
If this sounds like the right approach, I'll see if I can code some specific aspects. If it isn't the approach you're after, please could you give me a bit more information on how these 20 people would be identified?

You could also use some unique device-identifier. There was an intersting article about that on the Android Developers Blog.
If you want to create a build-script, you can use Ant.

Related

Retrieve TYPE_TOUCH and TYPE_GESTURE in AccessibilityService

I am developing an application which is supposed to collect user's interaction with Android device (touch related data) similar to this SO post.
I've tried all of the answer's suggested approaches starting from an app overlay with and without WATCH_OUTSIDE_TOUCH flag. getevent approach is also not an option for me as it requires root or external storage (as the answer states).
So I've created an AccessibilityService and now I am able to detect such events as: VIEW_CLICKED, VIEW_SCROLLED. However in the documentation I've encountered also GESTURE_DETECTION_START, GESTURE_DETECTION_END, TOUCH_INTERACTION_STARTand TOUCH_INTERACTION_END. I would like to use them to measure the interaction time. Unfortunately my service is not retrieving this events at all despite proper (?) configuration. My current configuration looks like:
AndroidManifest.xml:
...
<service
android:name=".accessibility.MyAccessibilityService"
android:label="#string/accessibility_service_label"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityervice"
android:resource="#xml/accessibility_config" />
</service>
...
accessibility_config.xml:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:description="#string/accessibility_service_description"
android:notificationTimeout="5"
android:summary="#string/accessibility_service_description" />
Summing up, my service is starting and retrieving some events properly, but it lacks gesture and touch start/end events. I've tried many other configurations including all capabilities and flags enabled but without any effect. Also I tried overriding a method AccessibilityService::onGesture but it's never called. Are this events available only in touch exploration mode?
I've described my problem maybe a little too broad, but I would appreciate any help or suggestions even not related strictly to AccessibilityService approach.
After some struggling I found out what was the problem (or set of problems):
My accessibility_config.xml file was invalid because it contained <?xml version="1.0" encoding="utf-8"?> tag, and according to the docs
This meta-data must reference an XML resource containing < accessibility-service > tag
So I deducted that it needs this and only this tag to work correctly.
GESTURE_DETECTION_START, GESTURE_DETECTION_END, TOUCH_INTERACTION_START and TOUCH_INTERACTION_END are events available only in touch exploration mode.
So android:canRequestTouchExplorationMode="true" and android:accessibilityFlags="flagRequestTouchExplorationMode" were missing in my config. The docs enlist those events under Exploration types.
EDIT:
sharing the final accessibility_settings.xml file:
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeViewTextChanged|typeViewFocused|typeViewLongClicked|typeViewClicked|typeViewScrolled|typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackHaptic"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:canRetrieveWindowContent="true"
android:description="#string/accessibility_service_description"
android:notificationTimeout="10"
android:settingsActivity="org.example.ExampleActivity" />

Edit or Change Views/Activities Mobile Quality Assurance (MQA) IBM

I'm using MQA and I'm trying to edit the form fields where the fields are declared to send feedback or bug report. I understand that default activities declared:
<activity android:name="com.ibm.mqa.ui.ProblemActivity" />
<activity android:name="com.ibm.mqa.ui.FeedbackActivity" />
<activity android:name="com.ibm.mqa.ui.ScreenshotEditorActivity" />
I have been reading the documentation and I have not found a way to edit these views / layouts.
You aren't able to edit the way the MQA form looks or functions when submitting bugs or feedback.

I can't get the Cast Companion Library notification to work

I am using the Cast Companion Library and it is mostly working fine, I get the mini player, and also the lock screen controls and the activity for playing content, but I can never get the notification screen to show. I am doing the following when initializing:
mCastMgr.enableFeatures(VideoCastManager.FEATURE_NOTIFICATION |
VideoCastManager.FEATURE_LOCKSCREEN |
VideoCastManager.FEATURE_DEBUGGING);
and I am doing the incrementUiCounter() on resume and decrementUiCounter() on pause.
I don't see any errors, I just don't see what I am doing wrong. The only thing I am missing is that I am not passing URLs for images when telling media to play because my URLs are local assets to my app and I'm just not sure how to pass those.
Are you using that with your own app or with CastVideos-android? If your own app, first I suggest you try the CastVideos-android app to make sure that works for you.
I suggest you print out the value of mVisibilityCounter in BaseCastManager.incrementUiCounter() and decrementUiCounter() to see if as you move in and out of different activities, it reflects the correct counter. When that counter reaches zero, then notification should show up. If the counter is reaching zero and the notification doesn't show up, I suggest you check your manifest file and see if you have the following in your Manifest:
<service
android:name="com.google.sample.castcompanionlibrary.notification.VideoCastNotificationService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.sample.castcompanionlibrary.action.toggleplayback" />
<action android:name="com.google.sample.castcompanionlibrary.action.stop" />
<action android:name="com.google.sample.castcompanionlibrary.action.notificationvisibility" />
</intent-filter>
</service>
(you can copy-and-paste from the CastVideos-android manifest file). You may have grabbed what it is from the documentation; there is an error there (I am planning to update a bunch of things tonight or tomorrow and the documentation will be updated as well); basically when the counter reaches zero, it calls into the notification service (see the onUiVisibilityChanged() in VideoCastManager) and if that action in manifest is not correctly set, the notification never gets our memo! Let me know if that is not the issue.
I had the same trouble. Just an FYI to those looking at this in 2016. The manifest entry is now different. I suggest to grab whatever is in the manifest of the CastVideos-android project.
<receiver android:name="com.google.android.libraries.cast.companionlibrary.remotecontrol.VideoIntentReceiver" />
<service
android:name="com.google.android.libraries.cast.companionlibrary.notification.VideoCastNotificationService" />
<service android:name="com.google.android.libraries.cast.companionlibrary.cast.reconnection.ReconnectionService"/>

Voice command for apps in Google Glass?

I have an android app developed to run on the google glass. And I run it using the adb. is it possible to give configure a voice command so that I can trigger it by saying "Ok GLASS" + "My Command" ??
Update - After XE16 update the following method does not work, the new solution is here Why is my voice command missing from the ok glass menu in XE16?
What you have to do is,
Inside the manifest file add these tags under the service which you wanted to trigger on your voice command.
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger_start" />
And you have to create a folder called xml inside res and add a xml file named as voice_trigger_start.xml.
Inside that add these lines
<?xml version="1.0" encoding="utf-8"?>
<trigger keyword="#string/its_me_amalan" />
Open the values folder inside the res folder and edit strings.xml, so it will look like this
<resources>
<string name="app_name">Amalan</string>
<string name="its_me_amalan">Hello Amalan</string>
<string name="stop">Stop</string>
</resources>
Now install the app onto Glass and say "ok glass, Hello Amalan" and the app opens.
Reference: http://pathofacoder.com/2013/11/20/google-glass-adding-your-own-voice-commands-to-your-apps/
Yesterday, Google released the XE12 firmware update, which put us into trouble with all custom launchers. Both Launcher2.apk and Launchy stopped working for me so as a workaround I implemented a method which is also a good answer to your question. Take a look at this page http://divingintoglass.blogspot.com/
I did this for a Glassware app developed with the GDK in this commit:
https://github.com/luisdelarosa/HelloGlass/commit/c5038ed2ff019306becb32211354358833b6fafc
Here is what is in that commit step-by-step:
Modify the AndroidManifest.xml to add a VoiceTrigger intent, inside either the Activity or the Service you want to launch via voice. Note that you can also optionally delete the Launcher intent since Glass does not use those like traditional Android.
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/glass_voice_trigger" />
Add the VoiceTrigger XML that the VoiceTrigger intent references, which should contain the string that you want the user to activate your app. In this case, we're calling it res/xml/glass_voice_trigger.xml
<?xml version="1.0" encoding="utf-8"?>
<trigger keyword="#string/glass_voice_trigger"/>
Optionally, put the string in the previous step into a strings.xml file. (You could have also just hardcoded that string into the VoiceTrigger XML as the value of the keyword attribute of the trigger node.) In this case, it is at res/values/strings.xml and our trigger is "say hello". Replace this string with whatever you want the user to say to launch your app.
<string name="glass_voice_trigger">say hello</string>
Don't forget to use permission since XE16 :
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />

Android widget in emulator

I have an existing android app.
I added a simple widget to it using the following:
updated my manifest with a <receiver> block which provides information about my AppWidgetProvider implementation
added a new xml files in res/xml with a <appwidget-provider> element that contains the height/width/updatePeriod/initialLayout/icon/label attributes
added a simple default layout with an ImageView and a TextView
implemented my AppWidgetProvider
When I build and deploy this to the emulator my Widget doesn't show up in the list of widgets. Am I missing some step to 'install' the widget? Do I need to do anything special to make it appear in the emulator?
EDIT:
Here's what my manifest receiver looks like:
<receiver android:name=".MyAppWidgetProvider"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/my_appwidget_info" />
</receiver>
and here's what my my_appwidget_info.xml looks like:
<?xml version="1.0" encoding="UTF-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:icon="#drawable/ic_logo"
android:label="MySampleApp"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="#layout/my_app_widget" >
</appwidget-provider>
Does your receiver tag in the manifest have the proper intent-filter and meta-data? It should look like the example in the documentation:
<receiver android:name="MyAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/my_appwidget_info" />
</receiver>
The receiver needs both of those pieces to be recognized as an app widget.
Edit: The <receiver> tags also need to be located inside the <application> tags.
If your app is installed on the SD card, all your widgets will quietly refuse to show up in the list. (The docs do make it clear that you can't have widgets if you're on the external storage).
You can go to the settings in the home screen, go to Applications, and go to your app. If it offers you to "Move to phone", then it is on the SD card. You can set the install location to internalOnly to prevent it from going onto the SD card.
If you do allow installation on SD card (because users will typically ask for that), they need to be clear that they can't have the widget in that case. If an app is on SD card and you want to use the widget, you first have to move the app back to internal storage and then reset the phone (!).
I had the same issue as well. A few things to check that can stop it from showing up on different models.
1)Must have a minHeight and minWidth set on AppWidget-Provider in the xml, if you remove either of those and launch in emulator, your widget will be gone.
2)Some models have issues if you don't supply a previewImage in the AppWidget-Provider
3)Some models can have issues if you install on the SD Card rather than internally, although I still prefer to install on SD Card.
4)Some models need to have an Activity with Main and Launcher defined even if you don't intend on using any Activities. (You can simply make a dummy one that says 'this is a widget app only'
5)You have to have your manifest setup correctly as shown in TinJa's answer.
I fought through this for quite a while before finally getting it to show up in all models and emulators, so be patient, make sure you aren't missing anything and set the values that need to be there. Remember some phones cache the Widget List and may not update until you have launched your first Activity or Rebooted the phone.
Hope that helps.
Sam
I had the same problem then I finally figure it out. Usually when you emulate an application, it has an activity to load. For a widget-only app, that isn't the case, but the IDE still thinks you're trying to launch an activity.
To change this go to your Build Options
then change the Launch Options to Nothing
I had the same problem. It turned out I accidentally had two meta-data resource xml files in two different folders, my "layout" folder and my "xml" folder. It was finding the (empty) resource in "layout" first, and using that for its meta-data.
It was a stupid mistake, but make sure you have only one xml file of that name that's pointed to in your receiver meta-data tag. Also I think it should always be in the xml folder.
I had the same problem.
And my problem was that I have /layout/main.xml file when I delete it the widget appear!
It sound like #ubzack answer but I think he talk about something else [same xml file name]

Categories

Resources