[Q] Set multiple alarms with single BroadcastReceiver. Weird behaviors. - Java for Android App Development

Good morning people,
I decided to ask here advice about an issue.
I'm working with AlarmManagers and a BroadcastReceiver, and I want to set 2(or more) alarms using a single BroadcastReceiver within a function.
My problem is that only the earliest alarm is received by the BroadcastReceiver at the right time, while the following alarm is received more than 5 minutes late or not at all.
I tried a lot of configurations, but I can't find where I'm wrong. Note that I'm using different request codes for my PendingIntents.
I should specify that the second alarm could be set a minute later than the 1st, which is my case. It seems that the BroadcastReceiver can't handle the second alarm, something like it's busy.
I can't try the code on a real android device now, so I'm using the emulator with Android Studio, so I don't really know whether the issue is caused by the emulator or not.
P.S. From my last tests it seems the second alarm triggers only at certain times. I can set it at every hour and minute I want, but it only starts at HH:00, HH:15, HH:30, HH:45, and so on O_O.
Please, it's driving me mad.
Thanks in advance for help.
Activity code:
Code:
public class mainActivity extends Activity {
final static int START = 0, STOP = 1;
AlarmManager alarmManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doneButtonClick(View view) {
int startHour = Integer.parseInt(((EditText)findViewById(R.id.startHour)).getText().toString());
int startMinute = Integer.parseInt(((EditText)findViewById(R.id.startMin)).getText().toString());
int stopHour = Integer.parseInt(((EditText)findViewById(R.id.stopHour)).getText().toString());
int stopMinute = Integer.parseInt(((EditText)findViewById(R.id.stopMin)).getText().toString());
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
setAlarm(START, startHour, startMinute);
setAlarm(STOP, stopHour, stopMinute);
}
private void setAlarm(int type, int hour, int minute) {
Intent intent = new Intent(this, MyReceiver.class);
intent.putExtra("type", type);
PendingIntent pIntent = PendingIntent.getBroadcast(this, type, intent, PendingIntent.FLAG_NO_CREATE);
if (pIntent != null) {
Log.d("alarm", "existing");
alarmManager.cancel(pIntent);
}
pIntent = PendingIntent.getBroadcast(this, type, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.HOUR_OF_DAY, hour);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pIntent);
}
}
BroadcastReceiver code:
Code:
public class MyReceiver extends BroadcastReceiver {
final static int START = 0, STOP = 1;
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
int type = intent.getExtras().getInt("type");
Log.d("alarm", "received");
switch(type) {
case START:
Log.d(String.valueOf(START), "start");
break;
case STOP:
Log.d(String.valueOf(STOP), "stop");
break;
}
}
}
Android Manifest:
Code:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".mainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver">
</receiver>
</application>
Results:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}

simone.bellandi.dev said:
Good morning people,
I decided to ask here advice about an issue.
I'm working with AlarmManagers and a BroadcastReceiver, and I want to set 2(or more) alarms using a single BroadcastReceiver within a function.
My problem is that only the earliest alarm is received by the BroadcastReceiver at the right time, while the following alarm is received more than 5 minutes late or not at all.
I tried a lot of configurations, but I can't find where I'm wrong. Note that I'm using different request codes for my PendingIntents.
I should specify that the second alarm could be set a minute later than the 1st, which is my case. It seems that the BroadcastReceiver can't handle the second alarm, something like it's busy.
I can't try the code on a real android device now, so I'm using the emulator with Android Studio, so I don't really know whether the issue is caused by the emulator or not.
P.S. From my last tests it seems the second alarm triggers only at certain times. I can set it at every hour and minute I want, but it only starts at HH:00, HH:15, HH:30, HH:45, and so on O_O.
Please, it's driving me mad.
Thanks in advance for help.
Activity code:
Code:
public class mainActivity extends Activity {
final static int START = 0, STOP = 1;
AlarmManager alarmManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doneButtonClick(View view) {
int startHour = Integer.parseInt(((EditText)findViewById(R.id.startHour)).getText().toString());
int startMinute = Integer.parseInt(((EditText)findViewById(R.id.startMin)).getText().toString());
int stopHour = Integer.parseInt(((EditText)findViewById(R.id.stopHour)).getText().toString());
int stopMinute = Integer.parseInt(((EditText)findViewById(R.id.stopMin)).getText().toString());
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
setAlarm(START, startHour, startMinute);
setAlarm(STOP, stopHour, stopMinute);
}
private void setAlarm(int type, int hour, int minute) {
Intent intent = new Intent(this, MyReceiver.class);
intent.putExtra("type", type);
PendingIntent pIntent = PendingIntent.getBroadcast(this, type, intent, PendingIntent.FLAG_NO_CREATE);
if (pIntent != null) {
Log.d("alarm", "existing");
alarmManager.cancel(pIntent);
}
pIntent = PendingIntent.getBroadcast(this, type, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.HOUR_OF_DAY, hour);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pIntent);
}
}
BroadcastReceiver code:
Code:
public class MyReceiver extends BroadcastReceiver {
final static int START = 0, STOP = 1;
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
int type = intent.getExtras().getInt("type");
Log.d("alarm", "received");
switch(type) {
case START:
Log.d(String.valueOf(START), "start");
break;
case STOP:
Log.d(String.valueOf(STOP), "stop");
break;
}
}
}
Android Manifest:
Code:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".mainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".MyReceiver">
</receiver>
</application>
Results:
Click to expand...
Click to collapse
AlarmManager has been made low priority to minimize wakelocks and battery drainage from KitKat and up.
You will have to use the new setExact() method;
https://developer.android.com/reference/android/app/AlarmManager.html#setExact%28int,%20long,%20android.app.PendingIntent%29

Thank you very much, it works perfectly, I've been looking for a solution for lot of time
I just thought "setRepeating" was the solution against "setInexactRepeating".
I didn't found anything like "setExactRepeating". Does it mean that I have to set next alarm in the BroadcastReceiver each time it's received?
Thanks again

Related

Catch ACTION_MEDIA_BUTTON - Intent from BT-Headset

Hi Community,
I have problems with the ACTION_MEDIA_BUTTON - Intent. I can't get my App receiving those actions and react on them.
In my AndroidManifest.xml I added the Intent-filter:
Code:
<intent-filter android:priority="42">
<action android:name="android.intent.action.MEDIA_BUTTON">
</intent-filter>
And in the onCreate-Method I registered a Receiver:
Code:
BroadcastReceiver receiver;
if (receiver == null) {
receiver = new ButtonReceiver();
}
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_BUTTON);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(receiver, filter);
And the corresponding ButtonReceiver-class:
Code:
class ButtonReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent)
{
String intentAction = intent.getAction();
if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction))
{
Log.d("ButtonReceiver", "I will handle buttons here");
//handle buttons
}
}
}
The app compiles fine and is also running without problems, BUT I never get to the "//handle buttons"-section.
For testing purpose I'm using my Jabra BT2015 and the provided earphones from HTC. Both don't work.
Every hint is very appreciated.
Greez
LordAlien

Can anyone tell me how am i going to do the following layout view?

How will i come about doing the view for this application shown with the link below? I'm new to eclipse/java. Can someone guide me along? Thanks
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
This is what i tried so far in my xml file but it isn't even close to what was shown in the link above...
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@android:id/tabs"></TabWidget>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@android:id/tabcontent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab1"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab2"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/tab3"></LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>
Can someone guide me along please?? I wanted it such that each tab has its own preferences for user to configure settings, can someone guide me please, i'm kinna new to java/android...
http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
Have a look at this tablayout tutorial.
I can't see a link...?
Prehaps you can go to this link to take a look http://www.androidzoom.com/android_applications/transportation/black-box_sgzi_screenshots.html
I suppose i wanted to use tabs and preferences together but is it possible to integrate both together in the xml file?
imso said:
I suppose i wanted to use tabs and preferences together but is it possible to integrate both together in the xml file?
Click to expand...
Click to collapse
Yes you can do it quite easily, but not in one xml file like you are trying.
You need to have a tablayout xml layout and activity like in that tutorial, and then create a tabspec for each of your preferences activities and add them to the tabhost.
Everything you need is in this tutorial.
http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
Erm i'm kinna new in android/java but how should i create the preferences programmatically for each tabs? can you guide me on this?
this is what i tried for my tab1.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Video">
<CheckBoxPreference
android:title="Audio"
android:defaultValue="True"
android:summary="Select W/O Audio"
android:key="AudioPref" />
<ListPreference
android:title="Video Encoder"
android:summary="Select the video encoding type"
android:key="EncodingPref"
android:defaultValue=""
android:entries="@array/EncodingType"
android:entryValues="@array/updateEncodingType" />
<ListPreference
android:title="Video Resolution"
android:summary="Select the video resolution"
android:key="ResolutionPref"
android:defaultValue=""
android:entries="@array/VideoResolution"
android:entryValues="@array/updateVideoResolution" />
</PreferenceCategory>
</PreferenceScreen>
But how should i display the above layout display to my Tab1Activity.java file?
Code:
public class Tab1Activity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Code:
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab1);
}
I don't really get the point of your question. Why don't you just use the preference options to create muliple levels of preferences.
Take a closer look at preferencescreen for example. You can create multilevel preference screens using basic Android code without the use of custom layouts.
Yes i have tried that and succeeded in creating multiple tab screen.. but bow i have other problem related to retrieving the video resolution for my ListPreference...
Q1. What are the available different forms of video encoding type available in android for user to choose from? Because i'm currently doing a video recording app which i wanted to use ListPreference to allow user to dynamically choose what type of encoding is available.
Q2. I wanted to know is there any easy way to retrieve video resolution on the actual phone? Because different phone has different phone resolution's compatibility, so i wanted to retrieve the resolution data and display the different resolutions dynamically into my ListPreference for user selection... Does it have to do with a method name "flatten()" i don't quite know what is the method... I'm kinna new in java/android, can someone guide me on how should i do that?
My mainActivity.java file
Code:
public class CameraTest extends Activity implements SurfaceHolder.Callback {
private static final String TAG = "Exception";
public static SurfaceView surfaceView;
public static SurfaceHolder surfaceHolder;
public static Camera MainCamera;
private static boolean previewRunning;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
surfaceView = (SurfaceView)findViewById(R.id.surface_camera);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//getparameters
Button btnStart = (Button) findViewById(R.id.button4);
btnStart.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
startService(new Intent(getApplicationContext(), ServiceRecording.class));
}
});
Button btnStop = (Button) findViewById(R.id.button5);
btnStop.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
stopService(new Intent(getApplicationContext(), ServiceRecording.class));
}
});
Button btnSetting = (Button) findViewById(R.id.button2);
btnSetting.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
startActivity(new Intent(getApplicationContext(), SettingActivity.class));
}
});
}
public static boolean ServiceStatus;
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(ServiceRecording.recordingStatus)
{
stopService(new Intent(getApplicationContext(), ServiceRecording.class));
try {
Thread.sleep(4000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
MainCamera = ServiceRecording.ServiceCamera;
startService(new Intent(getApplicationContext(), ServiceRecording.class));
}
else{
MainCamera = Camera.open();
if (MainCamera != null) {
Camera.Parameters params = MainCamera.getParameters();
params.setPreviewSize(320, 240);
params.setPreviewFormat(PixelFormat.JPEG);
MainCamera.setParameters(params);
try {
MainCamera.setPreviewDisplay(holder);
}
catch (IOException e)
{
e.printStackTrace();
}
MainCamera.startPreview();
previewRunning = true;
}
else {
Toast.makeText(getApplicationContext(), "Camera not available!", Toast.LENGTH_LONG).show();
finish();
}
}
if (previewRunning) {
MainCamera.stopPreview();
}
/*ServiceStatus = ServiceRecording.recordingStatus;
if(ServiceStatus == true)
{
stopService(new Intent(getApplicationContext(), ServiceRecording.class));
if (MainCamera != null) {
Camera.Parameters params = MainCamera.getParameters();
MainCamera.setParameters(params);
MainCamera.startPreview();
}
}*/
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
MainCamera.stopPreview();
previewRunning = false;
MainCamera.release();
}
}
My Preference.xml file
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Video">
<CheckBoxPreference
android:title="Audio"
android:defaultValue="True"
android:summary="Select w/o Audio"
android:key="AudioPref" />
<ListPreference
android:title="Video Encoder"
android:defaultValue="3"
android:summary="Set the Video Encoding Type"
android:key="EncodingPref"
android:entries="@array/EncodingType"
android:entryValues="@array/updateEncodingType"
android:dialogTitle="Video Encoding Format" />
<ListPreference
android:title="File Format"
android:defaultValue="3gp"
android:summary="Select the File Format"
android:key="FileFormatPref"
android:entries="@array/FileFormat"
android:entryValues="@array/updateFileFormat"
android:dialogTitle="File Format" />
<ListPreference
android:title="Video Resolution"
android:defaultValue=""
android:summary="Set the video resolution"
android:key="ResolutionPref"
android:dialogTitle="Video Resolution" />
</PreferenceCategory>
</PreferenceScreen>

[Q] nullpointer and wrap_content problems

Hello there
I got 2 problems:
Firstly, if I launch the following code on my device, I'm getting a nullpointer, and I got no idea why. ( I know it's sorta basic stuff)
Secondly, I want toset the screen height and lenght to wrap_content, it's red marked in the code...that is also not working..
Could you maybe help out a noob?
Code:
public class Game extends Activity implements OnClickListener{
Button start_time;
Button sec;
int i = 0;
TextView textview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
start_time = (Button) findViewById(R.id.start_time);
start_time.setOnClickListener(this);
textview1 = (TextView) findViewById(R.id.textView1);
/*
sec = (Button) findViewById(R.id.sec);
sec.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
long totalTime = SystemClock.elapsedRealtimeNanos()- startTime;
Intent intent = new Intent(Game.this, MainScreen.class);
intent.putExtra("time",totalTime);
startActivity(intent);
}
});
*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.game, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
Random r = new Random();
int x = r.nextInt([COLOR="Red"]wrap_content[/COLOR]);
int y = r.nextInt([COLOR="Red"]wrap_content[/COLOR]);
long startTime = SystemClock.elapsedRealtime();
i++;
View b = findViewById(R.id.start_time);
b.setX(x);
b.setY(y);
if (i == 1 ) {
b.setX(+9);
b.setY(+5);
}
if (i == 2 ) {
b.setX(x);
b.setY(y);
}
if (i == 3 ) {
b.setX(x);
b.setY(y);
}
else if (i == 4) {
long difference = SystemClock.elapsedRealtime() - startTime;
Intent intent = new Intent(Game.this, MainScreen.class);
intent.putExtra("time",difference);
// Toast.makeText(getApplicationContext(), getIntent().getStringExtra("time"), Toast.LENGTH_LONG).show();
textview1.setText(getIntent().getStringExtra("time"));
finish();
}
}
}
For the wrap_content one, you need to set that property to the view that holds the integer text, you can't set a height and width properties to an integer, only a view or other widgets such as buttons. So for you you should set the properties of the view with ID start_time to wrap_content for width and height - recommend doing this in the layout XML instead of java code.
I'm guessing that if you sort that out your null pointer will disappear.
Additionally in your public onClick(View v) method you should check the ID of the view before doing any function code, this means you can have multiple objects using the same listener.
So this:
Code:
@Override
public void onClick(View v) {
Random r = new Random();
... etc
Should become this:
Code:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_time:
Random r = new Random();
... etc
tahnks @Jonny for your answer, I changed the code, but now, my button isn't placed randomly on each click anymore, and I'm getting the nullpointer again. have a look:
Code:
public class Game extends Activity implements OnClickListener{
Button start_time;
Button sec;
int i = 0;
TextView textview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
start_time = (Button) findViewById(R.id.start_time);
start_time.setOnClickListener(this);
textview1 = (TextView) findViewById(R.id.textView1);
/*
sec = (Button) findViewById(R.id.sec);
sec.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
long totalTime = SystemClock.elapsedRealtimeNanos()- startTime;
Intent intent = new Intent(Game.this, MainScreen.class);
intent.putExtra("time",totalTime);
startActivity(intent);
}
});
*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.game, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
Random r = new Random();
int x = r.nextInt(+1);
int y = r.nextInt(+1);
long startTime = SystemClock.elapsedRealtime();
i++;
View b = findViewById(R.id.wrap_content);
b.setX(x);
b.setY(y);
if (i == 1 ) {
b.setX(+9);
b.setY(+5);
}
if (i == 2 ) {
b.setX(x);
b.setY(y);
}
if (i == 3 ) {
b.setX(x);
b.setY(y);
}
else if (i == 4) {
long difference = SystemClock.elapsedRealtime() - startTime;
Intent intent = new Intent(Game.this, MainScreen.class);
intent.putExtra("time",difference);
// Toast.makeText(getApplicationContext(), getIntent().getStringExtra("time"), Toast.LENGTH_LONG).show();
textview1.setText(getIntent().getStringExtra("time"));
finish();
}
}
}
and the xml
Code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="ch.asddd.af.Game" >
<Button
android:id="@+id/start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="139dp"
android:text="Button" />
<Button
android:id="@+id/sec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/start_time"
android:layout_below="@+id/start_time"
android:layout_marginLeft="17dp"
android:layout_marginTop="89dp"
android:text="Button"
android:visibility="gone"/>
<View
android:id="@+id/wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>
thank you. I'm really happy, there exists such great help
i have now changed the view start_time to a button...because it actually IS a button (im stupid) but now, when I click on the button, it moves completely out of the screen, and if not, instead of getting the time, the app stopps again with nullpointer. It should stay in the screen, placed randomly on click and after some clicks, I want to recieve the elapsed time. what is this?
code:
Code:
public class Game extends Activity implements OnClickListener{
Button start_time;
Button sec;
int i = 0;
TextView textview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
start_time = (Button) findViewById(R.id.start_time);
start_time.setOnClickListener(this);
textview1 = (TextView) findViewById(R.id.textView1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.game, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
Random r = new Random();
int x = r.nextInt(R.id.wrap_content);
int y = r.nextInt(R.id.wrap_content);
long startTime = SystemClock.elapsedRealtime();
i++;
Button b = (Button) findViewById(R.id.start_time);
b.setX(x);
b.setY(y);
if (i == 1 ) {
b.setX(+9);
b.setY(+5);
}
if (i == 2 ) {
b.setX(x);
b.setY(y);
}
if (i == 3 ) {
b.setX(x);
b.setY(y);
}
else if (i == 4) {
long difference = SystemClock.elapsedRealtime() - startTime;
Intent intent = new Intent(Game.this, MainScreen.class);
intent.putExtra("time",difference);
// Toast.makeText(getApplicationContext(), getIntent().getStringExtra("time"), Toast.LENGTH_LONG).show();
textview1.setText(getIntent().getStringExtra("time"));
finish();
}
}
}
and the xml:
Code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="chdfss.dsfwegg.trhhGame" >
<Button
android:id="@+id/start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="139dp"
android:text="Button" />
<Button
android:id="@+id/sec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/start_time"
android:layout_below="@+id/start_time"
android:layout_marginLeft="17dp"
android:layout_marginTop="89dp"
android:text="Button"
android:visibility="gone"/>
<View
android:id="@+id/wrap_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</View>
</RelativeLayout>
I'm not familiar with the nextInt() function (I can look it upp later when I'm home) but I'm pretty sure you shouldn't be parsing a views ID as one of its conditions - eg you're doing nextInt(R.id.wrap_content), are you sure that's right?

TabbedActivity (FragmentActivity): IllegalStateException: No Host, cannot reproduce

Hey All,
I've fixed quite some bugs, annoyances and crashes in our Android App and so far it looks good but a new crash has appeared which didn't occur before (probably because in the past it crashed before it even reached that point).
I tried to reproduce this crash on multiple different phones (Nexus 5, Nexus 4, Xiaomi Mi4C, Samsung Galaxy S5, HTC One A9 and A8) by rotating, switching tabs, turning screen off/on and switching tabs and rotating and so on but I just couldn't reproduce it .
Stacktrace:
Code:
java.lang.IllegalStateException: No host
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1194)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1189)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:2001)
at android.support.v4.app.Fragment.performActivityCreated(SourceFile:1976)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1051)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1207)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1189)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(SourceFile:2001)
at android.support.v4.app.Fragment.performActivityCreated(SourceFile:1976)
at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1051)
at android.support.v4.app.FragmentManagerImpl.attachFragment(SourceFile:1385)
at android.support.v4.app.BackStackRecord.run(SourceFile:728)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(SourceFile:1572)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(SourceFile:545)
at myPackageName.FragmentTabsActivity$TabManager.onTabChanged(SourceFile:183)
at android.widget.TabHost.invokeOnTabChangeListener(TabHost.java:468)
at android.widget.TabHost.setCurrentTab(TabHost.java:447)
at android.widget.TabHost$2.onTabSelectionChanged(TabHost.java:170)
at android.widget.TabWidget$TabClickListener.onClick(TabWidget.java:550)
at android.view.View.performClick(View.java:5106)
at android.view.View$PerformClick.run(View.java:20329)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5912)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)
FragmentTabsActivity manifest entry:
Code:
<activity
android:name="myPackageName.FragmentTabsActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
onTabChanged implementation from FragmentTabsActivity (I left a bit more than what is probably needed):
Code:
public static class TabManager implements TabHost.OnTabChangeListener {
private final FragmentActivity mActivity;
private final TabHost mTabHost;
private final int mContainerId;
private final Map<String, TabInfo> mTabs= new HashMap<String, TabInfo>();
TabInfo mLastTab;
static final class TabInfo {
private final String mTag;
private final Class<?> mClss;
private final Bundle mArgs;
private Fragment mFragment;
TabInfo(String tag, Class<?> clazz, Bundle args) {
mTag= tag;
mClss= clazz;
mArgs= args;
}
}
static class DummyTabFactory implements TabHost.TabContentFactory {
private final Context mContext;
public DummyTabFactory(Context context) {
mContext= context;
}
@Override
public View createTabContent(String tag) {
View v= new View(mContext);
v.setMinimumWidth(0);
v.setMinimumHeight(0);
return v;
}
}
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
mActivity= activity;
mTabHost= tabHost;
mContainerId= containerId;
mTabHost.setOnTabChangedListener(this);
}
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
tabSpec.setContent(new DummyTabFactory(mActivity));
String tag= tabSpec.getTag();
TabInfo info= new TabInfo(tag, clss, args);
// Check to see if we already have a fragment for this tab, probably
// from a previously saved state. If so, deactivate it, because our
// initial state is that a tab isn't shown.
info.mFragment= mActivity.getSupportFragmentManager().findFragmentByTag(tag);
if (info.mFragment != null && !info.mFragment.isDetached()) {
FragmentTransaction ft= mActivity.getSupportFragmentManager().beginTransaction();
ft.detach(info.mFragment);
ft.commitAllowingStateLoss();
}
mTabs.put(tag, info);
mTabHost.addTab(tabSpec);
}
@Override
public void onTabChanged(String tabId) {
TabInfo newTab= mTabs.get(tabId);
if (mLastTab != newTab) {
FragmentTransaction ft= mActivity.getSupportFragmentManager().beginTransaction();
if (mLastTab != null) {
if (mLastTab.mFragment != null) {
ft.detach(mLastTab.mFragment);
}
}
if (newTab != null) {
if (newTab.mFragment == null) {
newTab.mFragment= Fragment.instantiate(mActivity, newTab.mClss.getName(), newTab.mArgs);
ft.add(mContainerId, newTab.mFragment, newTab.mTag);
} else {
ft.attach(newTab.mFragment);
}
}
if (newTab.mFragment != null && newTab.mFragment instanceof MyMapFragment) {
MyMapFragment mapFragment= (MyMapFragment) newTab.mFragment;
mapFragment.clearBundleOnTabChange();
}
if (mLastTab != null && mLastTab.mFragment != null && mLastTab.mFragment instanceof MyMapFragment) {
MyMapFragment mapFragment= (MyMapFragment) mLastTab.mFragment;
mapFragment.clearBundleOnTabChange();
}
mLastTab= newTab;
ft.commitAllowingStateLoss();
mActivity.getSupportFragmentManager().executePendingTransactions();
}
}
}
FragmentTabsActivity is hosting 3 tabs where as every tab has one assigned Fragment.
If anyone knows how to reproduce/solve this I would be really happy about an answer. I've already found 2 or 3 possible solutions while googling but without being able to test which one actually solves my problem I feel uncomfortable :/
If needed and if it helps I can also add and describe the lifecycle of the FragmentTabsActivity and the hosted fragments
No ideas?

[Tutorial] Learn to create an Anagram Game for Android

Hello,
In that tutorial, you are going to learn how to create an Anagram game for Android by using Android Studio.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
But what is an Anagram ?
An anagram is direct word switch or word play, the result of rearranging the letters of a word or phrase to produce a new word or phrase, using all the original letters exactly once; for example, the word anagram can be rearranged into “nag a ram”.
Note that you can discover this tutorial in video on YouTube :
Create the User Interface
To start, we are going to create the User Interface of our Anagram game. In our User Interface, we will have a TextView to display the anagram. Then, an EditText to let the users to enter the word they found. And finally both buttons : one to validate the word entered and another to start a new game.
We make some customizations on these views. For example, we center them horizontally and this gives us the following code :
Code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/wordTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:text="Word To Find"
android:textSize="22sp"
android:textStyle="bold" />
<EditText
android:id="@+id/wordEnteredEt"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="@id/wordTv"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:inputType="textCapCharacters" />
<Button
android:id="@+id/validate"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="@id/wordEnteredTv"
android:layout_centerHorizontal="true"
android:layout_marginTop="60dp"
android:text="Validate" />
<Button
android:id="@+id/newGame"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_below="@id/validate"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp"
android:text="New Game" />
</RelativeLayout>
Core of the Anagram Game
Now, we can create the core of our game : the Anagram class. We will use this class to generate new words to find and to shuffle the word to find. Note that the list of words used for the game will be defined in this class :
Code:
package com.ssaurel.anagram;
import java.util.Random;
/**
* Created by ssaurel on 05/09/2017.
*/
public class Anagram {
public static final Random RANDOM = new Random();
public static final String[] WORDS = {"ACCOUNT", "ADDITION",
"AGREEMENT", "ANGRY", "ANIMAL", "BEHAVIOUR", "BETWEEN", "BLACK", "CHEMICAL", "FOOLISH",
"FREQUENT", "GOVERNMENT", "GRAIN", "GRASS", "HOSPITAL", "PAYMENT", "POLITICAL",
"PROCESS", "SHAME", "SMASH", "SMOOTH", "STATEMENT", "SUBSTANCE", "TEACHING", "TENDENCY",
"TOMORROW", "TOUCH", "UMBRELLA", "WEATHER", "YESTERDAY"};
public static String randomWord() {
return WORDS[RANDOM.nextInt(WORDS.length)];
}
public static String shuffleWord(String word) {
if (word != null && !"".equals(word)) {
char a[] = word.toCharArray();
for (int i = 0; i < a.length; i++) {
int j = RANDOM.nextInt(a.length);
char tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return new String(a);
}
return word;
}
}
Code of the Main Activity
Now, we can write the Java code of the main activity. The code is pretty simple. We get references of the views in the onCreate method. Then we install OnClickListener for both buttons.
In the validate method, we are going to check if the word entered by the user if equal to the word to find. If yes, we display a message of congratulations to the user and we start a new game by calling the newGame method.
The newGame method is used to start a new Anagram game. We generate a random word to find by calling the randomWord method of the Anagram class. Then, we shuffle this word via the shuffleWord method of the Anagram class. Finally, we display the word shuffled on the screen. The game starts and the user must find the word.
This gives us the following code :
Code:
package com.ssaurel.anagram;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView wordTv;
private EditText wordEnteredTv;
private Button validate, newGame;
private String wordToFind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wordTv = (TextView) findViewById(R.id.wordTv);
wordEnteredTv = (EditText) findViewById(R.id.wordEnteredEt);
validate = (Button) findViewById(R.id.validate);
validate.setOnClickListener(this);
newGame = (Button) findViewById(R.id.newGame);
newGame.setOnClickListener(this);
newGame();
}
@Override
public void onClick(View view) {
if (view == validate) {
validate();
} else if (view == newGame) {
newGame();
}
}
private void validate() {
String w = wordEnteredTv.getText().toString();
if (wordToFind.equals(w)) {
Toast.makeText(this, "Congratulations ! You found the word " + wordToFind, Toast.LENGTH_SHORT).show();
newGame();
} else {
Toast.makeText(this, "Retry !", Toast.LENGTH_SHORT).show();
}
}
private void newGame() {
wordToFind = Anagram.randomWord();
String wordShuffled = Anagram.shuffleWord(wordToFind);
wordTv.setText(wordShuffled);
wordEnteredTv.setText("");
}
}
Play to our Anagram Game
Now, it’s time to play to our Anagram Game. We launch the Anagram Game on an Android device and we see the following screen :
We have to enter the word to find in the EditText and then clicking to the validate button to win the game.
That’s all for that tutorial. To discover more tutorials on Android Development, don’t hesitate to subscribe to the SSaurel’s Channel on YouTube : https://www.youtube.com/channel/UCXoh49OXVg1UGjgWX1JRvlw
You can also discover this tutorial directly on the SSaurel's Blog : https://www.ssaurel.com/blog/learn-to-create-an-anagram-game-for-android/
Don't hesitate to give it a try and give me your feedback.
Thanks.
Sylvain

Categories

Resources