3

I am trying to create a simple android widget that shows The time but uses a custom font. Anyone knows how to do this? I've tried this: Problem showing time using custom font

But it will not work. First getAssets() will not work because it needs the context and if I remove the line that sets up the custom font after a couple of seconds I will get the failed binder transaction error.

Anyone can help or give me a link to a tutorial? Also is it a good practice to update the time with a timer?

My code LWidget.java

public class LWidget extends AppWidgetProvider {

//=============================================================================================
//On Update
//=============================================================================================


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
    int[] appWidgetIds) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new MyTime(context, appWidgetManager), 1, 1000);



        //views.setImageViewBitmap(R.id.TimeView, buildUpdate(time));





    }
//=============================================================================================
//Timer class
//=============================================================================================

    private class MyTime extends TimerTask {
        RemoteViews remoteViews;
        AppWidgetManager appWidgetManager;
        ComponentName thisWidget;
        DateFormat timeformat = new SimpleDateFormat("kk:mm");
        public MyTime(Context context, AppWidgetManager appWidgetManager) {
        this.appWidgetManager = appWidgetManager;
        remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
        thisWidget = new ComponentName(context, LWidget.class);
    }

    @Override
    public void run() {
        Calendar ci = Calendar.getInstance();
        String time = timeformat.format(ci.getTime());
        remoteViews.setTextViewText(R.id.widget_textview,"Time = " + time);
        remoteViews.setImageViewBitmap(R.id.widget_imageview, buildUpdate(time));
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
        }
    }

//=============================================================================================
//bitmap font
//=============================================================================================
    public Bitmap buildUpdate(String time) 
{
        Bitmap myBitmap = Bitmap.createBitmap(160, 84, Bitmap.Config.ARGB_4444);
        Canvas myCanvas = new Canvas(myBitmap);
        Paint paint = new Paint();

        //if I remove the comment here, getAssets() will not work

        //Typeface clock = Typeface.createFromAsset(this.getAssets(),"fonts/Crysta.ttf");
        paint.setAntiAlias(true);
        paint.setSubpixelText(true);
       // paint.setTypeface(clock);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.WHITE);
        paint.setTextSize(65);
        paint.setTextAlign(Align.CENTER);
        myCanvas.drawText(time, 80, 60, paint);
        return myBitmap;
 }




//=============================================================================================
//On receive
//=============================================================================================
@Override
    public void onReceive(Context context, Intent intent) {
            // v1.5 fix that doesn't call onDelete Action
            final String action = intent.getAction();
            if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
            final int appWidgetId = intent.getExtras().getInt(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
                this.onDeleted(context, new int[] { appWidgetId });
            }
            } else {
                super.onReceive(context, intent);
            }
    }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_height="wrap_content">

<TextView android:id="@+id/widget_textview"
android:text="@string/widget_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_horizontal|center"
android:layout_marginTop="5dip"
android:padding="10dip"
android:textColor="@android:color/black"/>

<ImageView 
   android:id="@+id/widget_imageview"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   />

</LinearLayout>

ltime_widget_provider.xml

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dip"
android:minHeight="72dip"
android:updatePeriodMillis="10000"
android:initialLayout="@layout/main"
/>
Community
  • 1
  • 1
Vincenzo
  • 57
  • 1
  • 6

2 Answers2

2

You must use an AlarmManager instead of a Timer. You can not use a Timer because:

AppWidgetProvider is an extension of BroadcastReceiver, your process is not guaranteed to keep running after the callback methods return.

Use the code here for reference.

getAssets() will not work because it needs the context

onUpdate() provides a Context, no?

Community
  • 1
  • 1
Dheeraj Vepakomma
  • 26,870
  • 17
  • 81
  • 104
0

okay try this way :

static Context con;  

Typeface clock = Typeface.createFromAsset(con.getAssets(),"fonts/KacstLetter.ttf");
Ghasem
  • 14,455
  • 21
  • 138
  • 171
  • Your code lacks the assignment of `con`. With just these changes, it will result in an NPE. Besides that, there's no need to save the context in a static field, in fact it's a bad idea because the code cannot be reused in different contexts. Just go for a regular, non-static field instead. PS: Welcome to StackOverflow! – hiergiltdiestfu Apr 08 '15 at 07:36
  • sorry i mean " static Context con; " put it before > public Bitmap buildUpdate(String time) {// ... } – Randa Harb Apr 08 '15 at 08:36