用于在 Android 中打开/关闭相机手电筒的小部件
我正在开发一个用于打开/关闭手机摄像头 LED 的小部件。
我制作了一个可以像切换按钮(开/关)一样工作的小部件。
行为如下:有时,当我启用小部件时,LED 灯保持亮起。 但它不会打开/关闭相机 LED,但会更改图标。
我无法弄清楚真正的问题是什么。
同样的事情在活动(火炬灯应用程序)中工作得很好。
谁能解释一下我该如何解决我的问题?
我哪里出错了?
你可以看一下我到目前为止所做的代码
onUpdate
方法
@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
方法如下:
@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
方法
private void processOffClick() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
processOnClick方法
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;
}
}
I am developing a widget for turning on/off camera led of phone.
I have made a widget that can work like toggle button (on/off).
Behavior is like follows : Sometimes the led light remains on when i enable the widget.
But it doesnot turn on/off the camera led but it changes the icon.
I am not able to figure out whats the actual problem.
The same thing works fine in Activity (Torch Light Application).
Can anyone please explain me how can i solve my problem ?
Where i am going wrong ?
You can look at the code below that i have done so far
onUpdate
method
@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
method is as follows :
@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
method
private void processOffClick() {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
processOnClick
method
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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我遇到过类似的情况,我需要在 UI 线程上运行某些 android 代码......这仅在 Activity 中可用。我的解决方案 - 具有完全透明布局的活动。因此,当您完成操作时,您只会看到主屏幕(尽管没有响应),在您的情况下,这应该很快。
I had a similar situation where I need to run certain android code on the UI thread ... which is only available in an Activity. My solution - an activity with a completely transparent layout. So you just see your home screen (albeit unresponsive) while you complete your actions, which in your case should be pretty quick.
我有一个解决方案,虽然不是很好,但是有效。让小部件调用一个活动,并在活动中打开闪光灯,然后关闭活动。关闭它也是一样。如果这在活动中有效,那么该解决方案将有效。它不优雅但有效。我试过了。
I have one solution that is not great but works. Have the widget call an Activity, and in the Activity turn the flash on, and later close the Activity. The same to turn it off. If this works in the Activity then this solution will work. It's not elegant but works. I tried it.
过了好久,我才有空解决这个问题。
这就是我所做的。
FlashlightWidgetProvider
类:FlashlightWidgetReceiver 的广播接收器:
Manifest.xml
文件中所需的权限:同时在
Manifest.xml
文件中注册接收器:重要注意:如果您的手机支持
FLASH_MODE_TORCH
,则此代码非常有效。我已经在 Samsung Galaxy Ace 2.2.1 & 中进行了测试。 2.3.3.该代码不起作用,因为该设备没有 FLASH_MODE_TORCH。
在 HTC Salsa、Wildfire 中工作正常。
如果有人可以在这里测试并发布结果,那就最好了。
After a long time, I got free to solve this problem.
Here is what I did.
FlashlightWidgetProvider
class :and BroadcastReceiver for FlashlightWidgetReceiver :
Permission required in
Manifest.xml
file :Also register receivers in
Manifest.xml
file :Important Note : This code works perfect if your phone has
FLASH_MODE_TORCH
supported.I have tested in Samsung Galaxy Ace 2.2.1 & 2.3.3. The code is not working because that device has no FLASH_MODE_TORCH.
Works fine in HTC Salsa, Wildfire..
If anyone can test and post results here, it would be best.
处理来自
RemoteViews
的点击的最佳技术是创建一个调用服务的PendingIntent
,并在该服务中执行您想要的“操作”服务,包括您的小部件的任何其他RemoteViews
更新。您可以在意图附加中发送相关数据。该服务在最后调用stopSelf()
,因此它会关闭。您无法维护
BroadcastReceiver
中的任何状态;系统在任何可用线程上运行这些,并且在调用onReceive()
后不会维护对您的实例的任何引用。不保证在调用BroadcastReceiver
之间维护您的mCamera
变量。如果您确实需要维护状态,则必须在服务中执行此操作,并且不要使用
stopSelf()
(直到适当的时间)。您不需要 UI 线程来使用
Camera
类,除非您正在执行图像预览,这需要SurfaceHolder
(并且意味着 UI)。但是,您必须激活事件循环,否则Camera
不会向您发送回调,这是一个问题,因为Camera
主要是异步的。您可以在服务中执行此操作(请参阅HandlerThread
)并保持服务运行,直到release()
所有内容。无论哪个线程调用Camera.open()
都会收到回调。每个人都真正阅读过 App Widgets 部分吗?
http://developer.android.com/guide/topics/appwidgets/index.html
< strong>使用 AppWidgetProvider 类部分几乎说明了我在这里所说的内容。
The best technique for handling clicks from a
RemoteViews
is to create aPendingIntent
that calls a service, and perform the "stuff" you want in the service, including any additionalRemoteViews
updates for your widget. You can send along the relevant data in the intent extras. The service callsstopSelf()
at the end, so it shuts off.You cannot maintain any state in an
BroadcastReceiver
; the system runs those on any available thread, and doesn't maintain any reference to your instance after callingonReceive()
. YourmCamera
variable is not guaranteed to be maintained between invocations of yourBroadcastReceiver
.If you really need to maintain state, you must do it in the service, and don't use
stopSelf()
(until an appropriate time).You do not need a UI thread to use the
Camera
class, unless you are doing image preview, which requires aSurfaceHolder
(and implies a UI). You must, however, have an event loop active, orCamera
will not post callbacks to you, which is a problem sinceCamera
is primarily asynchronous. You can do this within a service (seeHandlerThread
) and keep your service running until it's time torelease()
everything. Whichever thread callsCamera.open()
will receive callbacks.Did everyone actually read the section on App Widgets?
http://developer.android.com/guide/topics/appwidgets/index.html
Using the AppWidgetProvider Class section says pretty much what I am saying here.