Widget pour allumer / éteindre la lampe de poche de l'appareil photo dans android
je développe un widget pour allumer/éteindre caméra led de téléphone.
j'ai fait un widget qui peut fonctionner comme bouton à bascule (on/off).
se comporte comme suit : parfois, la lumière led reste allumée lorsque j'active le widget. Mais il n'allume pas/éteint la led de la caméra mais il change l'icône.
je ne suis pas en mesure de comprendre quel est le problème réel.
La même chose fonctionne bien en Activité (Application De La Lampe Torche).
est-ce que quelqu'un peut m'expliquer comment je peux résoudre mon problème ?
Où je vais mal ?
Vous pouvez regarder le code ci-dessous que j'ai fait jusqu'à présent
onUpdate
méthode
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
//super.onUpdate(context, appWidgetManager, appWidgetIds);
remoteViews = new RemoteViews( context.getPackageName(), R.layout.widgetlayout);
watchWidget = new ComponentName( context, FlashLightWidget.class );
Intent intentClick = new Intent(context,FlashLightWidget.class);
intentClick.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, ""+appWidgetIds[0]);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetIds[0],intentClick, 0);
remoteViews.setOnClickPendingIntent(R.id.myToggleWidget, pendingIntent);
appWidgetManager.updateAppWidget( watchWidget, remoteViews );
ctx=context;
}
onReceive
méthode est la suivante:
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
remoteViews = new RemoteViews( context.getPackageName(), R.layout.widgetlayout);
if (intent.getAction()==null) {
Bundle extras = intent.getExtras();
if(extras!=null) {
if(status)
{
status=false;
remoteViews.setImageViewResource(R.id.myToggleWidget, R.drawable.shutdown1);
processOnClick();
Toast.makeText(context,"Status==false-onclick",Toast.LENGTH_SHORT).show();
}
else
{
status = true;
remoteViews.setImageViewResource(R.id.myToggleWidget, R.drawable.shutdown2);
processOffClick();
Toast.makeText(context,"Status==true--Ofclick",Toast.LENGTH_SHORT).show();
}
}
watchWidget = new ComponentName( context, FlashLightWidget.class );
(AppWidgetManager.getInstance(context)).updateAppWidget( watchWidget, remoteViews );
}
}
}
processOffClick
méthode
private void processOffClick() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
processOnClick
méthode
private void processOnClick() {
if(mCamera==null)
{
try {
mCamera = Camera.open();
} catch (Exception e) {
e.printStackTrace();
}
}
if (mCamera != null) {
Parameters params = mCamera.getParameters();
List<String> flashModes = params.getSupportedFlashModes();
if (flashModes == null) {
return;
} else {
params.setFlashMode(Parameters.FLASH_MODE_OFF);
mCamera.setParameters(params);
mCamera.startPreview();
String flashMode = params.getFlashMode();
if (!Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
if (flashModes.contains(Parameters.FLASH_MODE_TORCH)) {
params.setFlashMode(Parameters.FLASH_MODE_TORCH);
mCamera.setParameters(params);
}
}
}
} else if (mCamera == null) {
//Toast.makeText(ctx, "Camera not found", Toast.LENGTH_LONG).show();
return;
}
}
4 réponses
après un long moment, j'ai été libre de résoudre ce problème.
voilà ce que j'ai fait.
FlashlightWidgetProvider
classe:
public class FlashlightWidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent receiver = new Intent(context, FlashlightWidgetReceiver.class);
receiver.setAction("COM_FLASHLIGHT");
receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
et "BroadcastReceiver for FlashlightWidgetReceiver:
public class FlashlightWidgetReceiver extends BroadcastReceiver {
private static boolean isLightOn = false;
private static Camera camera;
@Override
public void onReceive(Context context, Intent intent) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
if(isLightOn) {
views.setImageViewResource(R.id.button, R.drawable.off);
} else {
views.setImageViewResource(R.id.button, R.drawable.on);
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(new ComponentName(context, FlashlightWidgetProvider.class),
views);
if (isLightOn) {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
isLightOn = false;
}
} else {
// Open the default i.e. the first rear facing camera.
camera = Camera.open();
if(camera == null) {
Toast.makeText(context, R.string.no_camera, Toast.LENGTH_SHORT).show();
} else {
// Set the torch flash mode
Parameters param = camera.getParameters();
param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
try {
camera.setParameters(param);
camera.startPreview();
isLightOn = true;
} catch (Exception e) {
Toast.makeText(context, R.string.no_flash, Toast.LENGTH_SHORT).show();
}
}
}
}
}
Permission requise dans Manifest.xml
fichier:
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
enregistre également les récepteurs dans Manifest.xml
fichier:
<receiver android:name=".FlashlightWidgetProvider" android:icon="@drawable/on" 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/flashlight_appwidget_info" />
</receiver>
<receiver android:name="FlashlightWidgetReceiver">
<intent-filter>
<action android:name="COM_FLASHLIGHT"></action>
</intent-filter>
</receiver>
Note importante : ce code fonctionne parfaitement si votre téléphone a FLASH_MODE_TORCH
pris en charge.
j'ai testé dans Samsung Galaxy Ace 2.2.1 & 2.3.3. Le code ne fonctionne pas car ce périphérique N'a pas de FLASH_MODE_TORCH.
fonctionne très bien dans HTC Salsa, Wildfire..
Si quelqu'un peut tester et de publier les résultats ici, ce serait mieux.
la meilleure technique pour gérer les clics d'un RemoteViews
est de créer un PendingIntent
qui appelle un service, et effectuer le "truc" que vous voulez dans le service, y compris toutes les mises à jour RemoteViews
supplémentaires pour votre widget. Vous pouvez envoyer les données pertinentes à l'intention des extras. Le service appelle stopSelf()
à la fin, donc il s'arrête.
vous ne pouvez maintenir aucun État dans un BroadcastReceiver
; le système exécute ceux sur n'importe quel fil disponible, et ne conserve aucune référence à votre instance après avoir appelé onReceive()
. Votre variable mCamera
n'est pas garantie d'être maintenue entre les invocations de votre BroadcastReceiver
.
si vous avez vraiment besoin de maintenir l'état, vous devez le faire dans le service, et ne pas utiliser stopSelf()
(jusqu'à un moment approprié).
vous n'avez pas besoin D'un thread pour utiliser la classe Camera
, à moins que vous ne fassiez un aperçu d'image, qui nécessite un SurfaceHolder
(et implique une assurance-chômage). Vous devez cependant avoir une boucle d'événement active, ou Camera
ne vous affichera pas de callbacks, ce qui est un problème puisque Camera
est principalement asynchrone. Vous pouvez le faire dans le cadre d'un service (voir HandlerThread
) et garder votre service actif jusqu'à ce qu'il soit temps de release()
tout. Quel que soit le thread qui appelle Camera.open()
, il recevra des callbacks.
est-ce que tout le monde a lu la section sur les Widgets D'application? http://developer.android.com/guide/topics/appwidgets/index.html
en utilisant la classe AppWidgetProvider section dit à peu près ce que je dis ici.
j'ai eu une situation similaire où je dois exécuter certains Code android sur le fil UI ... qui n'est disponible que dans une activité. Ma solution-une activité avec une mise en page complètement transparente. Donc, vous ne voyez que votre écran d'accueil (bien que ne réagissant pas) pendant que vous terminez vos actions, ce qui dans votre cas devrait être assez rapide.
j'ai une solution qui n'est pas grand, mais fonctionne. Demandez au widget d'appeler une activité, et dans L'activité allumez le flash, et plus tard fermez l'activité. De même pour l'éteindre. Si cela fonctionne, dans l'Activité, alors cette solution fonctionne. Ce n'est pas élégant, mais fonctionne. Je l'ai essayé.