我想创建曲棍球成绩的应用程序。在主页上,用户选择他最喜欢的球队,然后他会在片段“未来比赛”中看到他最喜欢的球队的比赛。
此后,他可以选择自己喜欢的匹配项(通过单击匹配项),然后,如果该匹配项中的分数发生了变化,则用户会收到有关分数变化的通知。
但是我有问题,因为当我看到将来的比赛时,在点击比赛后,应用程序会掉落。
我对解决这个问题一无所知。
我需要这方面的帮助。
public class Future_matches extends Fragment {
private static Future_matches fragment;
private int favorite_team_id;
private SharedPreferences sp;
private RecyclerView rv_futureMatches;
// private FutureMatchesAdapter adapter;
private List<FutureMatchModel> teams;
private SharedPreferences.Editor ed;
List<Thread> listOfActiveThreads;
private RecyclerView.Adapter<FutureMatchesHolder> adapter;
private RecyclerView.LayoutManager layoutManager;
public Future_matches() {
}
public static Future_matches newInstance() {
if (fragment == null)
fragment = new Future_matches();
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listOfActiveThreads = new ArrayList<>();
sp = getActivity().getSharedPreferences(Tools.PACKAGE_NAME, Context.MODE_PRIVATE);
favorite_team_id = sp.getInt(Tools.FAVORITE_TEAM_ID, -1);
ed = sp.edit();
}
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootview = inflater.inflate(R.layout.future_matches, container, false);
rv_futureMatches = rootview.findViewById(R.id.rv_future_matches);
RecyclerView.LayoutManager lm = new LinearLayoutManager(getActivity());
// rv_futureMatches.setLayoutManager(lm);
// rv_futureMatches.setHasFixedSize(true);
if (favorite_team_id == -1) {
Toast.makeText(getActivity(), R.string.warning_future_matches_choose_favorite_team, Toast.LENGTH_SHORT).show();
} else {
Tools.getApi().getFutureMatches(favorite_team_id, "2018-12-27", "2019-05-12").enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.code() == 200) {
teams = JsonTools.convertJsonToFutureMatches(response.body());
// JsonObject data = response.body();
layoutManager = new LinearLayoutManager(getActivity());
layoutManager = new LinearLayoutManager(getContext());
// adapter = new FutureMatchesAdapter(JsonTools.convertJsonToFutureMatches(data), new WeakReference<Context>(getActivity()));
adapter = new FutureMatchesAdapter(teams, new WeakReference<Context>(getActivity()), new FutureMatchesAdapter.TeamClickHandler() {
@Override
public void onClick(int id) {
takeCareOfChanges(id);
}
});
rv_futureMatches.setHasFixedSize(true);
rv_futureMatches.setLayoutManager(layoutManager);
rv_futureMatches.setAdapter(adapter);
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
return rootview;
}
private boolean isItemInList(int id) {
if (sp.contains(Tools.PREFS_PICKED_GAMES)) {
Set<String> result = sp.getStringSet(Tools.PREFS_PICKED_GAMES, null);
if (result.contains(Integer.toString(id))) {
return true;
} else {
return false;
}
} else
return false;
}
private void takeCareOfChanges(int id) {
if (sp.contains(Tools.PREFS_PICKED_GAMES)) {
Set<String> result = sp.getStringSet(Tools.PREFS_PICKED_GAMES, null);
if (isItemInList(id)) {
result.remove(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
quitService(id);
} else {
result.add(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
launchService(id);
}
} else {
Set<String> result = new HashSet<>();
result.add(Integer.toString(id));
ed.putStringSet(Tools.PREFS_PICKED_GAMES, result);
launchService(id);
}
ed.apply();
}
private void launchService(final int id){
getActivity().startService(new Intent().putExtra(Tools.INTENT_EXTRA_ID,id));
}
private void quitService(int id){
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(new Intent().setAction(Tools.INTENT_ACTION_STOP_SERVICE).putExtra(Tools.INTENT_EXTRA_ID,id));
}
}
public class GameChangeService extends Service {
private final static String TAG = "GameChangeService";
private BroadcastReceiver broadcastReceiver;
private Handler h;
private SharedPreferences sp;
Notification notif;
NotificationManager notifManager;
private SharedPreferences.Editor ed;
private Runnable r;
private int id;
private String CHANNEL_ID = "ID";
private int notifId = 1000;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
sp = getSharedPreferences(Tools.PACKAGE_NAME, Context.MODE_PRIVATE);
ed = sp.edit();
notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
h = new Handler();
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
stopSelf();
}
};
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter(Tools.INTENT_ACTION_STOP_SERVICE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
id = intent.getIntExtra(Tools.INTENT_EXTRA_ID, -1);
if (id == -1) {
stopSelf();
} else {
r = new Runnable() {
@Override
public void run() {
doStuff(id);
h.postDelayed(r, 15000);
}
};
h.post(r);
return Service.START_STICKY;
}
//TOTO TU JE VELMI DISKUTABILNE
return Service.START_STICKY;
}
private void doStuff(final int id) {
//TODO: Checkni pls ci je boxscore updatovany live alebo nie. Ak je tak ho mozes pouzit v IApiDefinition namiesto live feed
// JA> V schedule je s gamepk aj online zapas s golmi - staci to pouzit
ApiTools.getApi().getGame(id).enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (sp.contains(Integer.toString(id))) {
int povodnyPocetGolovVZapase = sp.getInt(Integer.toString(id), 0);
//Z responsu zistit kolko eventov je teraz v zapase, t.j. ci uz zapas zacal.
//Dalej zistit ci su tam nejake eventy, ktore maju typ goal alebo ENDGAME (asi).
//AK sa zmenil pocet golov, tak posli notifikaciu ze padol gol aj s novym stavom
JsonObject data = response.body();
//pouzijem lastmatchmodel, aj ked to nie je pre toto robene, ale data mi stacia aj z neho
//List<LastMatchModel> livezapasy = new ArrayList<>();
//vytiahnem si zoznam
JsonArray zoznamZapasovZJsonu = data.get("dates").getAsJsonArray();
for (int i = 0; i < zoznamZapasovZJsonu.size(); i++) {
//pouzijem lastmatchmodel, aj ked to nie je pre toto robene, ale data mi stacia aj z neho
LastMatchModel novyZapas = new LastMatchModel();
JsonObject zapasDate = zoznamZapasovZJsonu.get(i).getAsJsonObject();
JsonArray games = zapasDate.get("games").getAsJsonArray();
if (games.size() >= 1) {
JsonObject teams = games.get(0).getAsJsonObject().get("teams").getAsJsonObject();
int golyHostia = teams.get("away").getAsJsonObject().get("score").getAsInt();
String timHostia = teams.get("away").getAsJsonObject().get("team").getAsJsonObject().get("name").getAsString();
int golyDomaci = teams.get("home").getAsJsonObject().get("score").getAsInt();
String timDomaci = teams.get("home").getAsJsonObject().get("team").getAsJsonObject().get("name").getAsString();
if (golyDomaci + golyHostia != povodnyPocetGolovVZapase) {
Intent intent = new Intent(GameChangeService.this, MatchNotification.class);
PendingIntent pendingIntent = PendingIntent.getActivity(GameChangeService.this, 0, intent, 0);
createNotificationChannel();
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(GameChangeService.this, CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("GOAL")
.setContentText(timDomaci + golyDomaci + " vs " + golyHostia + timHostia)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
NotificationManagerCompat nm = NotificationManagerCompat.from(GameChangeService.this);
nm.notify(notifId, mBuilder.build());
}
}
}
} else {
int povodnyPocetEventovVZapase = 0;
//Z responsu zistit kolko eventov je teraz v zapase, t.j. ci uz zapas zacal.
//Dalej zistit ci su tam nejake eventy, ktore maju typ goal alebo ENDGAME (asi).
//AK sa zmenil pocet golov, tak posli notifikaciu ze padol gol aj s novym stavom
}
}
@Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(GameChangeService.TAG, "Nebavi to ");
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (h != null)
h.removeCallbacks(r);
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Name of the channel";
String description = "Description of the channel";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}
在Android Studio中运行,告知有关错误的信息:
https://ctrlv.cz/shots/2019/01/03/Y6RS.png
要么
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.luky.nhlvysledky, PID: 23251
java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { (has extras) }
at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1519)
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1560)
at android.app.ContextImpl.startService(ContextImpl.java:1532)
at android.content.ContextWrapper.startService(ContextWrapper.java:664)
at com.example.luky.nhlvysledky.Future_matches.launchService(Future_matches.java:148)
at com.example.luky.nhlvysledky.Future_matches.takeCareOfChanges(Future_matches.java:142)
at com.example.luky.nhlvysledky.Future_matches.access$300(Future_matches.java:33)
at com.example.luky.nhlvysledky.Future_matches$1$1.onClick(Future_matches.java:93)
at com.example.luky.nhlvysledky.RecycleView.FutureMatchesHolder$1.onClick(FutureMatchesHolder.java:46)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
最佳答案
您需要明确地定义要启动的服务。
getActivity().startService(new Intent(getActivity(), GameChangeService.class).putExtra(Tools.INTENT_EXTRA_ID,id));
您还需要在AndroidManifest.xml中定义您的服务。
<service android:enabled="true" android:name=".GameChangeService" />
关于java - 通知用户他最喜欢的比赛,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54026548/