eclipse - Android Widget - Click for action, update under 30 minutes, separate instances -
i've tried create widget that, on click calls routine on configuration activity, on update calls routine on configuration activity, update must under 30 minutes , instance created must work separately (in onupdate , in onclick).
the code below: click doesn't work (can't see toast message , other function) update works fine first instance multiple widget instance works bad: if create 2 instances between 10 seconds (and refresh set 20 seconds) update every 10 seconds.
that's manifest:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="it.fraschi.controllogiardinowg" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="17" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name="it.fraschi.controllogiardinowg.configurazione" android:label="@string/app_name" > <intent-filter> <action android:name="android.appwidget.action.appwidget_configure"/> </intent-filter> </activity> <receiver android:name="it.fraschi.controllogiardinowg.controllowidget" android:label="@string/app_name"> <intent-filter> <action android:name="android.appwidget.action.appwidget_update" /> </intent-filter> <intent-filter> <action android:name="it.fraschi.controllogiardinowg.controllowidget.action_widget_clicked"/> </intent-filter> <intent-filter> <action android:name="it.fraschi.controllogiardinowg.controllowidget.my_own_widget_update" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider" /> </receiver> </application> </manifest>
that's configuration:
package it.fraschi.controllogiardinowg; import java.util.calendar; import java.util.random; import android.os.bundle; import android.app.activity; import android.app.alarmmanager; import android.app.pendingintent; import android.appwidget.appwidgetmanager; import android.content.context; import android.content.intent; import android.content.sharedpreferences; import android.view.menu; import android.view.view; import android.view.view.onclicklistener; import android.widget.adapterview; import android.widget.button; import android.widget.edittext; import android.widget.remoteviews; import android.widget.spinner; import android.widget.toast; import android.widget.adapterview.onitemselectedlistener; public class configurazione extends activity { private static final string prefs_name = "it.fraschi.android.controllogiardinowg"; public static final string nome = "nome_"; private static long millis = 60000; private int mappwidgetid = appwidgetmanager.invalid_appwidget_id; private int selectedtextcolor; private int selectedbackgroundcolor; public configurazione() { super(); } @override public void oncreate(bundle icicle) { super.oncreate(icicle); // set result canceled. cause widget host cancel // out of widget placement if press button. setresult(result_canceled); // set view layout resource use. setcontentview(r.layout.activity_configurazione); // find widget id intent. intent intent = getintent(); bundle extras = intent.getextras(); if (extras != null) { mappwidgetid = extras.getint( appwidgetmanager.extra_appwidget_id, appwidgetmanager.invalid_appwidget_id); } // if gave intent without widget id, bail. if (mappwidgetid == appwidgetmanager.invalid_appwidget_id) { finish(); } //final spinner backgroundcolorselector = (spinner)findviewbyid(r.id.backgroundcolor); final button savebutton = (button)findviewbyid(r.id.btnsalva); final button cancelbutton = (button)findviewbyid(r.id.btncancel); final edittext editnome = (edittext)findviewbyid(r.id.editnome); /*textcolorselector.setonitemselectedlistener(new onitemselectedlistener() { @override public void onitemselected(adapterview<?> parentview, view selecteditemview, int position, long id) { selectedtextcolor = integer.parseint(getresources().getstringarray(r.array.textcolorsvalues)[textcolorselector.getselecteditemposition()]); } @override public void onnothingselected(adapterview<?> parentview) {} });*/ savebutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { final context context = configurazione.this; //prepare alarm service trigger widget intent intent = new intent(controllowidget.my_widget_update); pendingintent pendingintent = pendingintent.getbroadcast(configurazione.this, mappwidgetid, intent, 0); alarmmanager alarmmanager = (alarmmanager)getsystemservice(alarm_service); calendar calendar = calendar.getinstance(); calendar.settimeinmillis(system.currenttimemillis()); calendar.add(calendar.second, 30); alarmmanager.setrepeating(alarmmanager.rtc_wakeup, calendar.gettimeinmillis(), millis, pendingintent); //controllowidget.savealarmmanager(alarmmanager, pendingintent); /// sharedpreferences.editor prefs = context.getsharedpreferences(prefs_name, 0).edit(); prefs.putstring(nome + mappwidgetid, editnome.gettext().tostring()); prefs.commit(); // push widget update surface newly set prefix appwidgetmanager appwidgetmanager = appwidgetmanager.getinstance(context); controllowidget.updateappwidget(context, appwidgetmanager, mappwidgetid); // make sure pass original appwidgetid intent resultvalue = new intent(); resultvalue.putextra(appwidgetmanager.extra_appwidget_id, mappwidgetid); setresult(result_ok, resultvalue); finish(); } }); cancelbutton.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { finish(); } }); } /*@override public boolean oncreateoptionsmenu(menu menu) { // inflate menu; adds items action bar if present. getmenuinflater().inflate(r.menu.configurazione, menu); return true; }*/ static string getname(context context, string prefkey ,int appwidgetid) { sharedpreferences prefs = context.getsharedpreferences(prefs_name, 0); string valuename = prefs.getstring(prefkey + appwidgetid, "non trovato"); return valuename; } static string getcolor(context context, string prefkey, int appwidgetid){ ///test sharedpreferences prefs = context.getsharedpreferences(prefs_name, 0); string nome = prefs.getstring(prefkey + appwidgetid, "non trovato"); /// int number = (new random().nextint(100)); string color = "daconf"+integer.tostring(number)+nome; toast.maketext(context, "eseguito", toast.length_long).show(); return color; } }
that's widget:
import java.text.dateformat; import java.text.simpledateformat; import java.util.date; import java.util.random; import android.app.alarmmanager; import android.app.pendingintent; import android.appwidget.appwidgetmanager; import android.appwidget.appwidgetprovider; import android.content.componentname; import android.content.context; import android.content.intent; import android.os.bundle; import android.os.environment; import android.os.statfs; import android.widget.remoteviews; import android.widget.toast; public class controllowidget extends appwidgetprovider { public static string action_widget_clicked = "it.fraschi.controllogiardinowg.esegui"; public static string my_widget_update = "it.fraschi.controllogiardinowg.controllowidget.my_own_widget_update"; static string strwidgettext = ""; public static boolean choice = false; @override public void onreceive(context context, intent intent) { // todo auto-generated method stub //super.onreceive(context, intent); string currentdatetimestring = dateformat.getdatetimeinstance().format(new date()); if(my_widget_update.equals(intent.getaction())){ bundle extras = intent.getextras(); if(extras!=null) { appwidgetmanager appwidgetmanager = appwidgetmanager.getinstance(context); componentname thisappwidget = new componentname(context.getpackagename(), controllowidget.class.getname()); int[] appwidgetids = appwidgetmanager.getappwidgetids(thisappwidget); choice=false; onupdate(context, appwidgetmanager, appwidgetids); } toast.maketext(context, "widget update" +currentdatetimestring, toast.length_long).show(); } //test click if(action_widget_clicked.equals(intent.getaction())){ bundle extras = intent.getextras(); if(extras!=null) { appwidgetmanager appwidgetmanager = appwidgetmanager.getinstance(context); componentname thisappwidget = new componentname(context.getpackagename(), controllowidget.class.getname()); int[] appwidgetids = appwidgetmanager.getappwidgetids(thisappwidget); choice=true; onupdate(context, appwidgetmanager, appwidgetids); } toast.maketext(context, "widget premuto", toast.length_long).show(); } //testclick } @override public void onenabled(context context) { // todo auto-generated method stub //super.onenabled(context); toast.maketext(context, "onenabled()", toast.length_long).show(); } @override public void onupdate(context context, appwidgetmanager appwidgetmanager,int[] appwidgetids) { // todo auto-generated method stub //super.onupdate(context, appwidgetmanager, appwidgetids); final int n = appwidgetids.length; (int i=0; i<n; i++) { int appwidgetid = appwidgetids[i]; // create intent launch exampleactivity intent intent = new intent(context, controllowidget.class); intent.setaction(action_widget_clicked); intent.putextra(appwidgetmanager.extra_appwidget_id, appwidgetid); pendingintent pendingintent = pendingintent.getbroadcast(context, appwidgetid, intent, pendingintent.flag_update_current); // layout app widget , attach on-click listener // button remoteviews views = new remoteviews(context.getpackagename(), r.layout.widget); views.setonclickpendingintent(r.id.btnesegui, pendingintent); // tell appwidgetmanager perform update on current app widget appwidgetmanager.updateappwidget(appwidgetid, views); //updateappwidget(context, appwidgetmanager, appwidgetid); //toast.maketext(context, "onupdate(): " + string.valueof(i) + " : " + string.valueof(appwidgetid), toast.length_long).show(); } remoteviews remotewidget = new remoteviews(context.getpackagename(),r.layout.widget); } public static void updateappwidget(context context, appwidgetmanager appwidgetmanager,int appwidgetid){ //testonclick remoteviews remotewidget = new remoteviews(context.getpackagename(),r.layout.widget); /// intent esegui = new intent(context, controllowidget.class); esegui.setaction(action_widget_clicked); //intent esegui = new intent(controllowidget.action_widget_clicked); pendingintent pendingesegui = pendingintent.getbroadcast(context, appwidgetid, esegui, 0); remotewidget.setonclickpendingintent(r.id.btnesegui, pendingesegui); // // if (choice){ remoteviews updateviews = new remoteviews(context.getpackagename(), r.layout.widget); updateviews.settextviewtext(r.id.btnesegui, "[" + string.valueof(appwidgetid) + "]" + strwidgettext + configurazione.getcolor(context, configurazione.nome, appwidgetid)); appwidgetmanager.updateappwidget(appwidgetid, updateviews); toast.maketext(context, "onclick(): " + string.valueof(appwidgetid) + "\n" + strwidgettext, toast.length_long).show(); }else{ int number = (new random().nextint(100)); strwidgettext = integer.tostring(number); remoteviews updateviews = new remoteviews(context.getpackagename(), r.layout.widget); updateviews.settextviewtext(r.id.btnesegui, "[" + string.valueof(appwidgetid) + "]" + strwidgettext + configurazione.getname(context, configurazione.nome, appwidgetid)); appwidgetmanager.updateappwidget(appwidgetid, updateviews); toast.maketext(context, "updateappwidget(): " + string.valueof(appwidgetid) + "\n" + strwidgettext, toast.length_long).show(); } } static alarmmanager myalarmmanager; static pendingintent mypendingintent; @override public void ondeleted(context context, int[] appwidgetids) { // todo auto-generated method stub //super.ondeleted(context, appwidgetids); myalarmmanager.cancel(mypendingintent); toast.maketext(context, "ondeleted()", toast.length_long).show(); } static void savealarmmanager(alarmmanager talarmmanager, pendingintent tpendingintent){ myalarmmanager = talarmmanager; mypendingintent = tpendingintent; } }
*
for timing under 30 mins , multiple instances i've decided use 1 timer instances.
below code oncreate of configuration class:
private static long millis = 20000; sharedpreferences read = context.getsharedpreferences(prefs_name, 0); string firstinstance = read.getstring("firstinstance", "ko"); if (firstinstance.equals("ko")) { sharedpreferences.editor write = context.getsharedpreferences( prefs_name, 0).edit(); write.putstring("firstinstance", "ok"); write.commit(); intent intent = new intent(controllowidget.my_widget_update); pendingintent pendingintent = pendingintent.getbroadcast( configurazione.this, 0, intent, 0); alarmmanager alarmmanager = (alarmmanager) getsystemservice(alarm_service); calendar calendar = calendar.getinstance(); calendar.settimeinmillis(system.currenttimemillis()); calendar.add(calendar.second, 10); alarmmanager.setrepeating(alarmmanager.rtc_wakeup, calendar.gettimeinmillis(), millis, pendingintent); controllowidget.savealarmmanager(alarmmanager, pendingintent); }
revert process ondisabled of widgetclass:
@override public void ondisabled(context context) { // todo auto-generated method stub //super.ondisabled(context); sharedpreferences.editor write = context.getsharedpreferences(prefs_name, 0).edit(); write.putstring("firstinstance", "ko" ); write.commit(); myalarmmanager.cancel(mypendingintent); } static void savealarmmanager(alarmmanager talarmmanager, pendingintent tpendingintent){ myalarmmanager = talarmmanager; mypendingintent = tpendingintent; }
now, setting button action , own update: class declaration:
public static string action_widget_clicked = "your.packagename.action_widget_clicked"; public static string my_widget_update = "your.packagename.my_widget_update";
onreceive method:
@override public void onreceive(context context, intent intent) { // todo auto-generated method stub super.onreceive(context, intent); choice = false; // ////toast.maketext(context, intent.getaction(), // ////toast.length_long).show(); // choice=false; bundle extras = intent.getextras(); if (my_widget_update.equals(intent.getaction())) { choice = false; appwidgetmanager appwidgetmanager = appwidgetmanager .getinstance(context); componentname thisappwidget = new componentname( context.getpackagename(), controllowidget.class.getname()); int[] appwidgetids = appwidgetmanager .getappwidgetids(thisappwidget); onupdate(context, appwidgetmanager, appwidgetids); // ////toast.maketext(context, "autoupdate", // ////toast.length_long).show(); } else if (action_widget_clicked.equals(intent.getaction())) { // choice =true; appwidgetmanager appwidgetmanager = appwidgetmanager .getinstance(context); componentname thisappwidget = new componentname( context.getpackagename(), controllowidget.class.getname()); int[] appwidgetids = appwidgetmanager .getappwidgetids(thisappwidget); int appwidgetid = intent.getintextra( appwidgetmanager.extra_appwidget_id, -1); // //////// remoteviews remoteviews = new remoteviews(context.getpackagename(), r.layout.widget); remoteviews.settextviewtext(r.id.btnesegui, configurazione.getname(context, "nome", appwidgetid)); // action code here appwidgetmanager.updateappwidget(appwidgetid, remoteviews); log.d("log_esecuzione", "log esecuzione, widget n." + string.valueof(appwidgetid)); } }
then onupdate , updateappwidget method:
@override public void onupdate(context context, appwidgetmanager appwidgetmanager, int[] appwidgetids) { // todo auto-generated method stub // super.onupdate(context, appwidgetmanager, appwidgetids); final int n = appwidgetids.length; (int = 0; < n; i++) { int appwidgetid = appwidgetids[i]; updateappwidget(context, appwidgetmanager, appwidgetid); } } public static void updateappwidget(context context, appwidgetmanager appwidgetmanager,int appwidgetid){ //testonclick remoteviews remoteviews = new remoteviews(context.getpackagename(),r.layout.widget); intent myintent = new intent(context, controllowidget.class); myintent.setaction(action_widget_clicked); myintent.putextra(appwidgetmanager.extra_appwidget_id, appwidgetid); pendingintent pendingintent = pendingintent.getbroadcast(context,appwidgetid, myintent, 0); remoteviews.setonclickpendingintent(r.id.btnesegui, pendingintent); remoteviews.settextviewtext(r.id.btnesegui,configurazione.getname(context, "nome", appwidgetid)); //on update code, requested action when onupdate called (for widget), refresh pending intent appwidgetmanager.updateappwidget(appwidgetid, remoteviews); log.d("log_update", "log update, widget n."+string.valueof(appwidgetid)); } appwidgetmanager.updateappwidget(appwidgetid, remoteviews); }
for separate instances necessary:
on intentcreation:(on updateappwidget)
remoteviews remoteviews = new remoteviews(context.getpackagename(),r.layout.widget); intent myintent = new intent(context, controllowidget.class); myintent.setaction(action_widget_clicked); //the line below appwidgetid specification myintent.putextra(appwidgetmanager.extra_appwidget_id, appwidgetid); pendingintent pendingintent = pendingintent.getbroadcast(context,appwidgetid, myintent, 0); remoteviews.setonclickpendingintent(r.id.btnesegui, pendingintent);
on receiving broadcast: (on onreceive)
if (action_widget_clicked.equals(intent.getaction())){ //commented not used on example //appwidgetmanager appwidgetmanager = appwidgetmanager.getinstance(context); //componentname thisappwidget = new componentname(context.getpackagename(), controllowidget.class.getname()); //int[] appwidgetids = appwidgetmanager.getappwidgetids(thisappwidget); int appwidgetid = intent.getintextra(appwidgetmanager.extra_appwidget_id, -1);
now call routine everywhere passing appwidgetid , context function... example:
action.someaction(context,appwidgetid);
for update timer, possible (without using preferences): other intent use putextra
on broadcast: retrieve int on broadcast receive
int appwidgetid = intent.getintextra(appwidgetmanager.extra_appwidget_id, -1);
but don't call onupdate
method directly updateappwidget
alternative solution every widget has own time refresh (maybe configurable) i've preferred have 1 timer process active @ same time , widget updated @ first instance widget update time
Comments
Post a Comment