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]
Related
Question
Can I can set a default app on a build if two apps of the same category are
installed?
Example
I am adding a custom browser on AOSP. I want to set it as the default browser before the build starts.
On the Android.mk file for packages there is an option to specify 'LOCAL_OVERRIDES_PACKAGES' which basically overrides the install of the packages mentioned making my app as the default.
But I would want the other app to be a part of the ROM with my app as the default.
Any ideas will be appreciated.
So I found a solution for setting an application as default at build time. I am documenting it in the hope that it helps someone else down the line.
The Android system keeps a list of the default applications/activities in a block in a file located at /data/system/users/{*user-id*}/package-restrictions.xml called as <preferred-activities></preferred-activities>
This file is generated by the Settings.java and the PackageManager.java upon build time. Whenever the defaults on the android system change, the flags on this xml block change accordingly.
At build, the system reads a set of preferred-activities from an additional location which is /system/etc/preferred-activities/*.xml
In order to add our desired preferred/default activities we create an xml file and place it at /system/etc/preferred-activities/ which is then read by the android system and the list of preferred activities are added to the list in package-restrictions.xml
Example
Adding a custom browser to AOSP
If only the default browser is being installed on the device other
that 'mybrowser' the following xml file should be created. In this
case, I am naming it as preferred-activies-home.xml
<?xml version="1.0" encoding="UTF-8"?>
<preferred-activities>
<item name="com.mybrowser.MainActivity" match="200000" always="true" set="2">
<set name="com.mybrowser./.MainActivity" />
<set name="com.android.browser/.BrowserActivity" />
<filter>
<action name="android.intent.action.VIEW" />
<cat name="android.intent.category.DEFAULT" />
<scheme name="http" />
</filter>
</item>
</preferred-activities>
Copy the above xml to the /system/etc/preferred-apps/ location by adding the following line in <!--AOSP_SOURCE-->/build/target/product/full_base.mk
PRODUCT_COPY_FILES +=/<location-of-file>/preferred-activities-home.xml:system/etc/preferred-apps/preferred-activities-home.xml
After build, the browser activity will be set as default
Limitations and Caveats
There are some limitations to the above mentioned process. They are as follows:
Upon build time, we would need to know the main activity for ALL the
applications which are addressing the particular intent-filters.
The above process does not work for Launcher upon the first boot.
The presumption is that the ResolverActivity does not consider the
package-restrictions upon the startup.
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"/>
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" />
i have an application which associates pdf files in my Manifest(via intent-filters), so when someone click on pdf link in the default browser i can execute that action with my app and download it with a progressbar. my question is, is it a way that i can associate other files but not "hard coded" in my manifest, but to let the user choose(or write) that file extention in preferences for example and i can add it dynamically from code. i know that probably this can be done with broadcast receiver but cant find any examples or simple code for that matter. ive seen preference menu like that in bsplayer settings .. but cant post image cuz dont have enough reputation.
I will try to explain more detailed my problem, because i think that there was some misunderstanding with the answer below.
i have an application which have the fallowing code in my manifest.
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:host="*" />
<data android:pathPattern=".*\\.pdf" />
</intent-filter>
2.i launch my app which registers .pdf files with it. so next time i click on pdf link in my browser, a window pops up, making me choose with what application should i complete that action. if i choose my application, my main activity is launched, in which i use getIntent() and my app downloads the file using progressbar.
3.the problem is that i want to download and other files like that ie. jpg, png .. etc, but giving the user a choice which ones, or even making him write the extentions for the files he wants to download using my application if clicks on link somewhere that leads to that kind of files.
4.to make this thing happen, file extensions should be added dynamically in code somewow and not in manifest. i was looking some examples for broadcast receiver, since that class can use IntentFilter class, but cant really understand what i should be doing with it.
5.My main goal: starting my app, there is layout with some spinner or edit box. the user choose/writes some extension (.dwf). that extension is now registered with my app. if the next time the user browsing internet clicks on link which leads to .dwf file he could choose to continue the action with my app. and the file should be downloaded just like the .pdf
6.sry for my bad english and some help will be appreciated. also code ;)
boolean enabled=prefs.getBoolean(key, false);
int flag=(enabled ?
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
ComponentName component=new ComponentName(MyActivity.this, TargetActivity.class);
getPackageManager()
.setComponentEnabledSetting(component, flag,
PackageManager.DONT_KILL_APP);
Depending upon your preference you can Disable the activity that handles the File type in your BOOT_COMPLETED Reciever. I Believe you will have to have different activities to handle different file types and then disable selectively
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.