小部件延迟和超时

时间:2013-10-24 07:57:40

标签: android android-intent service android-widget

这是一个相当普遍的问题。我用小部件制作了一个手电筒应用程序 它有效,但是:

  1. 闪光灯工作正常,但图标更改图像延迟。按下图标后,手电筒将打开,但图像会在约0.4秒后更改。 (通过较小的图片解决)
  2. 2。一天之后,我检查小部件并且它不起作用,但是如果我再次拉动小部件就可以了。

    是什么让这些事情发生?

    currentprovider.class

    public class CurrentProvider extends AppWidgetProvider {
        public static final String WIDGETTAG = "WidgetFlashLight";
    
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                int[] appWidgetIds) {
            super.onUpdate(context, appWidgetManager, appWidgetIds);
    
            Log.i(WIDGETTAG, "onUpdate");
    
            final int N = appWidgetIds.length;
    
            // Perform this loop procedure for each App Widget that belongs to this provider
            for (int i=0; i<N; i++) {
                int appWidgetId = appWidgetIds[i];
    
                Log.i(WIDGETTAG, "updating widget[id] " + appWidgetId);
    
                RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
    
                Intent intent = new Intent(context, CurrentService.class);
                intent.setAction(CurrentService.CHANGE_CAMERA_STATE);
                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
    
                views.setOnClickPendingIntent(R.id.widgetBtn, pendingIntent);
                Log.i(WIDGETTAG, "pending intent set");
    
                // Tell the AppWidgetManager to perform an update on the current App Widget
                appWidgetManager.updateAppWidget(appWidgetId, views);
            }
        }   
    }
    

    currentService.class

    public class CurrentService extends Service {
        public static final String CHANGE_CAMERA_STATE = "ChangeState";
        public static  boolean mFlashIsOn = false;
        public static Camera camera;
        public static Parameters params;
        private static final int NOTIFICATION_EX = 1;
        private NotificationManager notificationManager;
         Notification notification;
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            super.onStart(intent, startId);
    
            Log.i(CurrentProvider.WIDGETTAG, "onStartCommand");
    
            getCamera();
            switchCameraState(intent);
    
            stopSelf(startId);
    
            return START_STICKY;
        }
    
    
        private void switchCameraState(Intent intent) {
            Log.i(CurrentProvider.WIDGETTAG, "This is the intent " + intent);
            if (intent != null){
                String requestedAction = intent.getAction();
                Log.i(CurrentProvider.WIDGETTAG, "This is the action " + requestedAction);
                if (requestedAction != null && requestedAction.equals(CHANGE_CAMERA_STATE)){
    
    
                    int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
    
                    AppWidgetManager appWidgetMan = AppWidgetManager.getInstance(this);
                    RemoteViews views = new RemoteViews(this.getPackageName(),R.layout.widgetlayout);
    
                    switchFlash(views);
    
                    appWidgetMan.updateAppWidget(widgetId, views);
                    Log.i(CurrentProvider.WIDGETTAG, "State updated!");
                }
            }
        }
    
        public void getCamera() {
            if (camera == null) {
                try {
                    camera = Camera.open();
                    params = camera.getParameters();
                } catch (RuntimeException e) {
                    Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
                }
            }
        }
    
    
    
        public void switchFlash(RemoteViews views) {
            if (camera == null || params == null) {
                Log.i("camera||params","is null");
                return;
            }
            params = camera.getParameters();
    
            if (mFlashIsOn) {;
                params.setFlashMode(Parameters.FLASH_MODE_OFF);
                camera.setParameters(params);
                camera.stopPreview();
                views.setImageViewResource(R.id.widgetBtn, R.drawable.wi_off);
                mFlashIsOn=false;
                //setNotification(false);
                switchNotificationOff();
            }else{      
                params.setFlashMode(Parameters.FLASH_MODE_TORCH);
                camera.setParameters(params);
                camera.startPreview();
                views.setImageViewResource(R.id.widgetBtn, R.drawable.wi_on);
                mFlashIsOn=true;
                setNotification(true);
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        public void setNotification(boolean x){
    
            notificationManager = (NotificationManager) 
                getSystemService(Context.NOTIFICATION_SERVICE);
            int icon = R.drawable.icon;
            CharSequence tickerText = "Just FlashLight";
    
            notification = new Notification(icon, tickerText, 0);
            Context context = getApplicationContext();
            CharSequence contentTitle = "Just FlashLight";
            CharSequence contentText = "Press to stop flashlight";
            Intent notificationIntent = new Intent(this, StartScreen.class);
            PendingIntent contentIntent = PendingIntent.getActivity(this, 
                0, notificationIntent, 0);
            notification.setLatestEventInfo(context, contentTitle, 
                contentText, contentIntent);
            notificationManager.notify(NOTIFICATION_EX, notification);
        }
    
        public void switchNotificationOff( ){
            if (Context.NOTIFICATION_SERVICE!=null) {
                String ns = Context.NOTIFICATION_SERVICE;
                NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(ns);
                nMgr.cancel(NOTIFICATION_EX);
            }
        }
    }
    

    providerInfo.xml

    <?xml version="1.0" encoding="utf-8"?>
    <appwidget-provider
      xmlns:android="http://schemas.android.com/apk/res/android" 
      android:minWidth="72dp" 
      android:minHeight="72dp" 
      android:updatePeriodMillis="0" 
      android:initialLayout="@layout/widgetlayout">
    </appwidget-provider>
    

    widgetlayout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="0.1dp" >
    
    
        <ImageButton
            android:id="@+id/widgetBtn"
            android:layout_width="72dp"
            android:layout_height="72dp"
            android:layout_gravity="center_vertical"
            android:src="@drawable/wi_off" 
            android:scaleType="fitXY"
            android:background="@android:color/transparent" 
            >
        </ImageButton>
    
    </LinearLayout>
    

    清单:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.flashlight"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="10"
            android:targetSdkVersion="17" />
    
        <uses-permission android:name="android.permission.CAMERA" />
    
        <uses-feature android:name="android.hardware.camera" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/icon"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme" >
            <service android:name="com.flashlight.CurrentService" >
            </service>
    
            <receiver android:name="com.dimrix.flashlight.CurrentProvider" >
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    
                    <category android:name="android.intent.category.DEFAULT" >
                    </category>
                    <category android:name="android.intent.category.ALTERNATIVE" >
                    </category>
                </intent-filter>
                <intent-filter>
                    <action android:name="com.flashlight.CurrentService" />
                </intent-filter>
    
                <meta-data
                    android:name="android.appwidget.provider"
                    android:resource="@xml/widgetproviderinfo" />
            </receiver>
    
            <activity
                android:name="com.flashlight.StartScreen"
                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>
    
        </application>
    
    </manifest>
    

2 个答案:

答案 0 :(得分:1)

我还制作了一个闪光灯的应用程序,它工作正常,图像更改没有时间延迟。所以直到您不发布代码,很难猜出问题的原因。

对于第二个问题,当你的小部件冻结时,你必须得到!!! FAILED BINDER TRANSACTION !!!。这是许多开发人员面临的长期运行问题。但是你可以避免使用小部件中使用的小尺寸(内存)图像因为Binder可以只占用小于1.5MB的小内存。我也遇到同样的问题检查它hereNobody was able to answer it

答案 1 :(得分:0)

您可以使用AlarmManager替换刷新间隔android:updatePeriodMillis以警告您想要的每个间隔。 可能这link会帮助你。