如何解决制作一个在点击时播放特定声音的 Android 小部件
我正在编写一个音板应用程序,让用户可以在他们的主屏幕上放置一些小部件。它由一个由 Sound 类的 RecyclerView 扩充的 Widget ConfigureActivity 组成:
public class Sound {
private String name;
private int sound_id;
public Sound(String name,int sound_id) {
this.name= name;
this.id = id;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
当用户从 ConfigureActivity RecyclerView 中选择一个元素时,会创建一个小部件。但是,我发现当用户点击它时无法播放声音。
我的适配器如下所示:
public class AdapterDatosWidget extends RecyclerView.Adapter<AdapterDatosWidget.ViewHolderDatosWidget> {
private final ArrayList<Sonido> sonidos;
private AssignHandler handler;
public AdapterDatosWidget(ArrayList<Sound> sonidos,AssignHandler assignHandler) {
this.sonidos = sonidos;
handler = assignHandler;
}
@NonNull
@Override
public ViewHolderDatosWidget onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_widget,null,false);
return new AdapterDatosWidget.ViewHolderDatosWidget(view,handler);
}
@Override
public void onBindViewHolder(@NonNull ViewHolderDatosWidget holder,int position) {
holder.asignarDatos(sonidos.get(position));
}
@Override
public int getItemCount() {
return sonidos.size();
}
public static class ViewHolderDatosWidget extends RecyclerView.ViewHolder {
Sound s;
TextView name;
AssignHandler handler;
public ViewHolderDatosWidget(@NonNull View itemView,AssignHandler handler) {
super(itemView);
name = itemView.findViewById(R.id.sound_name);
this.handler = handler;
}
public void asignarDatos(Sound sonido) {
s = sonido;
name.setText(sonido.getNombre());
name.setonClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handler.assign(getAbsoluteAdapterPosition());
}
});
}
}
public interface AssignHandler {
void assign(int position);
}
}
Configure Activity 正确识别出被按下的声音,如下所示:
public class SoundWidgetConfigureActivity extends Activity implements AdapterDatosWidget.AssignHandler {
int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
RecyclerView recyclerView;
private static final String PREFS_NAME = "com.xvlaze.soundboard.soundWidget";
private static final String PREF_PREFIX_KEY = "appwidget_";
public SoundWidgetConfigureActivity() {
super();
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Set the result to CANCELED. This will cause the widget host to cancel
// out of the widget placement if the user presses the back button.
setResult(RESULT_CANCELED);
setContentView(R.layout.sound_widget_configure);
recyclerView = findViewById(R.id.recycler);
recyclerView.setLayoutManager(new linearlayoutmanager(this));
AdapterDatosWidget ad = new AdapterDatosWidget(sonidos,this);
recyclerView.setAdapter(ad);
findViewById(R.id.add_button).setonClickListener(mOnClickListener);
// Find the widget id from the intent.
Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
mAppWidgetId = extras.getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID);
}
// If this activity was started with an intent without an app widget ID,finish with an error.
if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
return;
}
}
View.OnClickListener mOnClickListener = new View.OnClickListener() {
public void onClick(View v) {
final Context context = SoundWidgetConfigureActivity.this;
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
SoundWidget.updateAppWidget(context,appWidgetManager,mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,mAppWidgetId);
setResult(RESULT_OK,resultValue);
finish();
}
};
// Write the prefix to the SharedPreferences object for this widget
static void saveTitlePref(Context context,int appWidgetId,String text) {
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME,0).edit();
prefs.putString(PREF_PREFIX_KEY + appWidgetId,text);
prefs.apply();
}
// Read the prefix from the SharedPreferences object for this widget.
// If there is no preference saved,get the default from a resource
static String loadTitlePref(Context context,int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME,0);
String titleValue = prefs.getString(PREF_PREFIX_KEY + appWidgetId,null);
if (titleValue != null) {
return titleValue;
} else {
return context.getString(R.string.appwidget_text);
}
}
static void deleteTitlePref(Context context,int appWidgetId) {
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME,0).edit();
prefs.remove(PREF_PREFIX_KEY + appWidgetId);
prefs.apply();
}
@Override
public void assign(int position) {
Toast.makeText(this,sonidos.get(position).getName(),Toast.LENGTH_SHORT).show();
final Context context = SoundWidgetConfigureActivity.this;
// When the button is clicked,store the string locally
//String widgetText = mAppWidgetText.getText().toString();
//saveTitlePref(context,mAppWidgetId,widgetText);
// It is the responsibility of the configuration activity to update the app widget
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
NewAppWidget.updateAppWidget(context,mAppWidgetId);
// Make sure we pass back the original appWidgetId
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,mAppWidgetId);
setResult(RESULT_OK,resultValue);
finish();
}
}
Widget 代码如下所示:
public class SoundWidget extends appwidgetprovider {
@Override
public void onUpdate(Context context,AppWidgetManager appWidgetManager,int[] appWidgetIds) {
RemoteViews img = new RemoteViews(context.getPackageName(),R.layout.sound_widget);
Intent playIntent = new Intent(context,PlaySoundService.class);
PendingIntent playPendingIntent = PendingIntent.getService(
context,playIntent,0);
img.setonClickPendingIntent(R.id.widget,playPendingIntent);
// There may be multiple widgets active,so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context,appWidgetId);
}
}
@Override
public void onDeleted(Context context,int[] appWidgetIds) {
// When the user deletes the widget,delete the preference associated with it.
for (int appWidgetId : appWidgetIds) {
SoundWidgetConfigureActivity.deleteTitlePref(context,appWidgetId);
}
}
@Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
@Override
public void ondisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
static void updateAppWidget(Context context,int appWidgetId) {
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.sound_widget);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId,views);
}
}
Service 的代码如下所示:
public class PlaySoundService extends Service {
private static final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this,R.raw.soundid);
//configure other settings
}
public int onStartCommand(Intent intent,int flags,int startId) {
player.start();
return Service.START_STICKY;
}
public void onStart(Intent intent,int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
@Override
public void onDestroy() {
player.stop();
player.release();
}
}
如果您重现此示例(请使用一些示例 mp3 文件填充 res/raw 文件夹),请调用:
Intent svc=new Intent(this,BackgroundSoundService.class);
startService(svc);
在 MainActivity 中,您会看到只要打开应用程序就会立即播放声音。我错过了什么吗?我简直不敢相信它那么复杂。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。