Show log messages on screen for Android application - android

Is it possible to display the log messages (which I print using android.util.Log) on screen in an Android application?
Is there any other better method to just output lines on the screen?
Something like System.out.println?

Like others have suggested, you can use log cat. If you are using the emulator or debugging a device, you can use adb logcat to view the messages. In Eclipse debug perspective, there is a window that will do that for you.
Another way, without a debugger attached, is to use the CatLog - Logcat Reader application.

Yes zero4
what you are attempting to do is dropping 'logcat' comand on android shell & getting command output as output stream.This link will help you.

I use "android.widget.Toast.makeText(Context context, CharSequence text, int duration)" to do something like what you are asking. Seems like the easiest way to get some quick messages on the screen and make it go away automatically (based on the last parameter).
:-)

Well, there is a solution to log anything you want on screen using this lib. It didn't worked for me, so I develop my own solution you can find an example of it here. It's really simple, just add a class OnScreenLog to your project
package br.com.ideiageni.onscreenlogSample;
import android.app.Activity;
import android.graphics.Color;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* Created by ariel on 07/07/2016.
*/
public class OnScreenLog {
private static int timeoutTime = 1000;
private static TextView tvLog;
private static int logCount = 0;
private static int logCountMax = 30;
private static String[] logs = new String[logCountMax];
private static int cntClicks = 0;
private static boolean visibility = false;
private static Activity activity;
private int maxClicks = 5;
public OnScreenLog(){}
public OnScreenLog(Activity activity, int ViewID){
OnScreenLog.activity = activity;
tvLog = new TextView(activity.getApplicationContext());
maintainLog("Log is working");
tvLog.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
tvLog.setTextColor(Color.BLACK);
tvLog.setBackgroundColor(Color.LTGRAY);
tvLog.setAlpha((float) 0.4);
View v = null;
LinearLayout linearLayout;
RelativeLayout relativeLayout;
try {
linearLayout = (LinearLayout) activity.findViewById(ViewID);
} catch (ClassCastException e) {linearLayout = null;};
try {
relativeLayout = (RelativeLayout) activity.findViewById(ViewID);
} catch (ClassCastException e) {relativeLayout = null;};
if(linearLayout != null) {
linearLayout.addView(tvLog);
v = linearLayout;
} else if(relativeLayout != null) {
relativeLayout.addView(tvLog);
v = relativeLayout;
}
if(v != null) {
v.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
cntClicks++;
timerHandler.removeCallbacks(rTimeout);
timerHandler.postDelayed(rTimeout, timeoutTime);
if (cntClicks > maxClicks-1) {
setLogVisible(!visibility);
timerHandler.removeCallbacks(rTimeout);
cntClicks = 0;
}
break;
}
return false;
}
});
}
}
public void log (String text){
String logText = text;
maintainLog(logText);
}
public void log (int text){
String logText = String.valueOf(text);
maintainLog(logText);
}
public void log (int[] text){
StringBuilder builder = new StringBuilder();
for (int i : text) {
builder.append(i);
builder.append("-");
}
String logText = builder.toString();
maintainLog(logText);
}
public void log (byte[] text){
StringBuilder builder = new StringBuilder();
for (int i : text) {
builder.append(i);
builder.append("-");
}
String logText = builder.toString();
maintainLog(logText);
}
private void maintainLog(String newText){
String logText = "";
if(logCount<logCountMax) logCount++;
for(int i=logCount-1; i>0; i--){
logs[i] = logs[i-1];
}
logs[0] = newText;
for(int i=0; i<logCount; i++){
if(i<logCount-1) logText+=logs[i]+System.getProperty("line.separator");
else logText+=logs[i];
}
tvLog.setText(logText);
}
public void clearLog(){
tvLog.setText("");
}
public void setLogVisible(boolean visibility){
if(visibility) tvLog.setVisibility(View.VISIBLE);
else tvLog.setVisibility(View.INVISIBLE);
OnScreenLog.visibility = visibility;
}
public static int getLogCountMax() {
return logCountMax;
}
public static void setLogCountMax(int logCountMax) {
OnScreenLog.logCountMax = logCountMax;
logs = new String[logCountMax];
}
public int getMaxClicks() {
return maxClicks;
}
public void setMaxClicks(int maxClicks) {
this.maxClicks = maxClicks;
}
Handler timerHandler = new Handler();
Runnable rTimeout = new Runnable() {
#Override
public void run() {
cntClicks = 0;
}
};
}
then, for instance:
public class Activity1 extends AppCompatActivity {
private OnScreenLog log;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_1);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
log = new OnScreenLog(this, R.id.content_1);
log.log("Started log on Activity 1");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), Activity2.class);
startActivity(intent);
log.log("Starting Activity 2");
Snackbar.make(view, "Starting Activity 2", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
Where R.id.content_1 is the name of the main LinearLayout or RelativeLayout of your activity.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/content_1"
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="br.com.ideiageni.onscreenlogSample.Activity1"
tools:showIn="#layout/activity_1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 1!" />
</RelativeLayout>
Neither solutions print the current log messages, so you'll need to tell it to log to screen the same informations you log today on your current log.
Work not finished yet but can be used for anyone in need. Missing some directions on how to use. Suggestions are welcome.

Related

Runtime Error, by starting the Application [duplicate]

This question already has answers here:
How to set Id of dynamic created layout?
(10 answers)
Closed 5 years ago.
I have written a small app in Android Studio. If I start the app in the emulator, then I get an exception. The application simply stops.
The source code looks as follows:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private int points, round, countdown;
private static final int FROG_ID = 212121;
private Random rnd = new Random();
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
#Override
public void run(){
countdown();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//newGame();
showStartFragment();
}
private void newGame(){
points = 0;
round = 1;
initRound();
}
private void initRound(){
countdown = 10;
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
WimmelView wv = new WimmelView(this);
container.addView(wv, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
wv.setImageCount(5*(10+round));
ImageView frog = new ImageView(this);
frog.setId(FROG_ID);
frog.setImageResource(R.drawable.frog1);
frog.setScaleType(ImageView.ScaleType.CENTER);
float scale = getResources().getDisplayMetrics().density;
FrameLayout.LayoutParams lp= new FrameLayout.LayoutParams(Math.round(64*scale),Math.round(61*scale));
lp.leftMargin = rnd.nextInt(container.getWidth()-64);
lp.topMargin = rnd.nextInt(container.getHeight()-61);
lp.gravity = Gravity.TOP + Gravity.START;
frog.setOnClickListener(this);
container.addView(frog, lp);
handler.postDelayed(runnable, 1000-round*50);
update();
}
private void fillTextView(int id, String text){
TextView tv = (TextView) findViewById(id);
tv.setText(text);
}
private void update(){
fillTextView(R.id.points, Integer.toString(points));
fillTextView(R.id.round, Integer.toString(round));
fillTextView(R.id.countdown,
Integer.toString(countdown*1000));
}
private void showStartFragment(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
container.addView(
getLayoutInflater().
inflate(R.layout.fragment_start, null));
container.findViewById(R.id.start).setOnClickListener(this);
}
private void showGameOverFragment(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.addView(
getLayoutInflater().
inflate(R.layout.fragment_gameover, null));
container.findViewById(play_again).setOnClickListener(this);
}
#Override
public void onClick(View view) {
if(view.getId()==R.id.start){
startGame();
}else if(view.getId()==R.id.play_again){
showStartFragment();
}else if(view.getId()==FROG_ID){
handler.removeCallbacks(runnable);
Toast.makeText(this,R.string.kissed, Toast.LENGTH_SHORT).show();
//showToast(R.string.kissed);
points += countdown*1000;
round++;
}
initRound();
}
private void startGame() {
newGame();
}
private void countdown(){
countdown--;
update();
if(countdown<=0){
//frog.setOnClickListener(null);
showGameOverFragment();
}else {
handler.postDelayed(runnable, 1000-round*50);
}
}
#Override
protected void onPause(){
super.onPause();
handler.removeCallbacks(runnable);
}
}
At the beginning I came so far that I could at least press on start, now I am not at all more in the application pure ...
I have tried to googlen what it could be, but I have not succeeded in doing so. I also get a error message at the point frog.setId (FROG_ID).
In addition, I have yet another class, which implements images
public class WimmelView extends View {
private Random rnd;
private long randomSeed = 1;
private int imageCount;
private Paint paint = new Paint();
private static final int[]
images = { R.drawable.frog2,
R.drawable.frog3,R.drawable.frog4,
R.drawable.frog5,R.drawable.frog6};
public void setImageCount(int imageCount){
this.imageCount = imageCount;
randomSeed = System.currentTimeMillis();
invalidate();
}
public WimmelView(Context context){
super(context);
paint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
rnd = new Random(randomSeed);
for(int image:images){
Bitmap bitmap =
BitmapFactory.decodeResource(getResources(),image);
for(int i=0; i<imageCount/images.length; i++){
float left = (float) (rnd.nextFloat()
*(getWidth()-bitmap.getWidth()));
float top = (float) (rnd.nextFloat()
*(getWidth()-bitmap.getWidth()));
canvas.drawBitmap(bitmap,left,top,paint);
}
bitmap.recycle();
}
}
}
I hope someone sees the error and can help me ...
Your error is that the Content view is removing all children from the screen including the textviews of the score and points that you are trying to use. I just helped you move to fragments offline and ensured you were good to go. Goodluck.
You can use this,
<item name="frog_id" type="id"/>
This give you unique value.
You add this in your ids.xml. and change your code
...
frog.setId(R.id.frog_id);
...
else if(view.getId()==R.id.frog_id)
Try this
This is related to setting the view id. You can't set the id with the following:
private static final int FROG_ID = 212121;
...
frog.setId(FROG_ID);
You need to define an id in res/values/ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="your_view_id" type="id"/>
</resources>
But this will against the purpose of creating a dynamic view.
Instead, you can use View.generateViewId for the id instead. But please remember that this method only work from API version 17. Here the excerpt:
int generateViewId ()
Generate a value suitable for use in setId(int). This value will not
collide with ID values generated at build time by aapt for R.id.

Android checkboxes, how to implement if statement.

I am currently coding an android app but I encountered some difficulty.
I am able to receive some checkbox values from another activity using the getIntent().getExtras().getBoolean()function.
But my question is, how can i make sure that checkboxes with the characters 'wb' or 'ab' or 'alb' together with(or not) 'cs' appearing, a count is performed and the one with the greatest value between 'wb', 'ab' and 'alb' is chosen and a summary is displayed via a texfield.
e.g. if there appearances of 'wb' are greater than those of 'alb' and ab, then the result is displayed "you have a widened bronchus".
package com.example.vic.cdmes_;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class results extends AppCompatActivity {
private Button displayResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_results);
viewResults();
}
private void viewResults() {
final Boolean wb1 = getIntent().getExtras().getBoolean("wb1");
final Boolean wb2 = getIntent().getExtras().getBoolean("wb2");
final Boolean wb3 = getIntent().getExtras().getBoolean("wb3");
final Boolean wb4 = getIntent().getExtras().getBoolean("wb4");
final Boolean wb5 = getIntent().getExtras().getBoolean("wb5");
final Boolean wb6 = getIntent().getExtras().getBoolean("wb6");
final Boolean wb7 = getIntent().getExtras().getBoolean("wb7");
final Boolean cs1 = getIntent().getExtras().getBoolean("cs1");
final Boolean cs2 = getIntent().getExtras().getBoolean("cs2");
final Boolean vb1 = getIntent().getExtras().getBoolean("vb1");
final Boolean vb2 = getIntent().getExtras().getBoolean("vb2");
final Boolean vb3 = getIntent().getExtras().getBoolean("vb3");
final Boolean vb4 = getIntent().getExtras().getBoolean("vb4");
final Boolean vb5 = getIntent().getExtras().getBoolean("vb5");
final Boolean alb1 = getIntent().getExtras().getBoolean("alb1");
final Boolean alb2 = getIntent().getExtras().getBoolean("alb2");
final Boolean alb3 = getIntent().getExtras().getBoolean("alb3");
final Boolean ab1 = getIntent().getExtras().getBoolean("ab1");
final Boolean ab2 = getIntent().getExtras().getBoolean("ab2");
final Boolean ab3 = getIntent().getExtras().getBoolean("ab3");
final Boolean ab4 = getIntent().getExtras().getBoolean("ab4");
displayResult = (Button)findViewById(R.id.displayResults);
displayResult.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(results.this,.toString(),
// Toast.LENGTH_SHORT).show();
if(wb1&&wb2&&wb3&&wb4&&wb5&&wb6&&wb7&&cs1&&cs2)
{
//if the number of checkboxes exceeds
}
else
if (vb1&&vb2&&vb3&&vb4&&vb5&&cs1&&cs2)
{
//display the person might be having a widened bronchus
}
else
if (alb1&&alb2&&alb3&&cs1&&cs2)
{
//display the person might be having a alb disease
}
else
if (ab1&&ab2&&ab3&&ab4&&cs1&&cs2)
{
//display the person might be having a airborne disease
}
}
});
}
}
thanks for the help in advance.
Set Default Boolean value. Like This
final Boolean wb1 = getIntent().getExtras().getBoolean("wb1",true);
You can get the count of wb, ab and alb below, using that you can write the if statement.
int wbCount = 0, abCount = 0, albCount = 0;
boolean cs = (cs1 && cs2);
for(int i=1; i <= 7; i++) {
if(getIntent().getExtras().getBoolean("wb"+i) && cs) {
wbCount++;
}
}
for(int i=1; i <= 3; i++) {
if(getIntent().getExtras().getBoolean("alb"+i) && cs) {
albCount++;
}
}
for(int i=1; i <= 4; i++) {
if(getIntent().getExtras().getBoolean("ab"+i) && cs) {
abCount++;
}
}

Adding ProgressBar to DetailsOverviewRow on Android TV

I'm trying to create a slightly modified version of the android.support.v17.leanback.widget.DetailsOverviewRow for an Android TV app. The layout I'm trying to accomplish is roughly the same as Google's default version, but with the addition of a progress bar above the actions panel. What I have now looks like this:
Current Version
What I want to create is something roughly like this:
Goal Version
I would like to add this in dynamically without having to create an entirely new layout from scratch if possible. Here's the code I'm using currently, slightly modified from the default Android TV app in Android Studio:
public class VideoDetailsFragment extends DetailsFragment {
private static final String TAG = "VideoDetailsFragment";
private static final int ACTION_UPDATE = 1;
private static final int ACTION_CHANGELOG = 2;
private static final int ACTION_INSTALLED = 3;
private static final int DETAIL_THUMB_WIDTH = 274;
private static final int DETAIL_THUMB_HEIGHT = 274;
private static final int NUM_COLS = 10;
private static final String UPDATE = "Update";
private Update mSelectedUpdate;
private Drawable mDefaultBackground;
private Target mBackgroundTarget;
private DisplayMetrics mMetrics;
private DetailsOverviewRowPresenter mDorPresenter;
private DetailRowBuilderTask mDetailRowBuilderTask;
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate DetailsFragment");
super.onCreate(savedInstanceState);
mDorPresenter =
new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
BackgroundManager backgroundManager = BackgroundManager.getInstance(getActivity());
backgroundManager.attach(getActivity().getWindow());
mBackgroundTarget = new PicassoBackgroundManagerTarget(backgroundManager);
mDefaultBackground = getResources().getDrawable(R.drawable.default_background);
mMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
List<Update> list = UpdateList.setupMovies();
mSelectedUpdate = list.get(0);//(Update) getActivity().getIntent().getSerializableExtra(MOVIE);
mDetailRowBuilderTask = (DetailRowBuilderTask) new DetailRowBuilderTask().execute(list);
mDorPresenter.setSharedElementEnterTransition(getActivity(),
DetailsActivity.SHARED_ELEMENT_NAME);
setOnItemViewClickedListener(new ItemViewClickedListener());
}
#Override
public void onStop() {
mDetailRowBuilderTask.cancel(true);
super.onStop();
}
private class DetailRowBuilderTask extends AsyncTask<List<Update>, Integer, List<DetailsOverviewRow>> {
#Override
protected List<DetailsOverviewRow> doInBackground(List<Update>... movies) {
List<DetailsOverviewRow> rows = new ArrayList<DetailsOverviewRow>();
int exampleUpdate = 0;
for (Update m: movies[0]) {
DetailsOverviewRow row = new DetailsOverviewRow(m);
try {
//String test = mSelectedUpdate.getCardImageUrl();
Bitmap poster = Picasso.with(getActivity())
.load(m.getCardImageUrl())
.resize(Utils.convertDpToPixel(getActivity().getApplicationContext(), DETAIL_THUMB_WIDTH),
Utils.convertDpToPixel(getActivity().getApplicationContext(), DETAIL_THUMB_HEIGHT))
.centerCrop()
.get();
row.setImageBitmap(getActivity(), poster);
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.toString(), e);
}
SparseArrayObjectAdapter adapter = new SparseArrayObjectAdapter();
if (exampleUpdate++ == 0) {
Action a1 = new Action(ACTION_UPDATE, getResources().getString(R.string.download));
Action a2 = new Action(ACTION_CHANGELOG, getResources().getString(R.string.release_notes));
adapter.set(ACTION_UPDATE, a1);
adapter.set(ACTION_CHANGELOG, a2);
row.setActionsAdapter(adapter);
}else{
Action a1 = new Action(ACTION_INSTALLED, getResources().getString(
R.string.installed));
Action a2 = new Action(ACTION_CHANGELOG, getResources().getString(R.string.release_notes));
//ProgressBar p1 = new ProgressBar(getActivity(),null, android.R.attr.progressBarStyleHorizontal);
adapter.set(1, a1);
adapter.set(2, a2);
//adapter.set(3, p1);
row.setActionsAdapter(adapter);
}
rows.add(row);
}
return rows;
}
#Override
protected void onPostExecute(List<DetailsOverviewRow> detailRows) {
ClassPresenterSelector ps = new ClassPresenterSelector();
// set detail background and style
mDorPresenter.setBackgroundColor(getResources().getColor(R.color.black_opaque));
Log.i("TEST", "Setting BG Color of Detail View");
mDorPresenter.setStyleLarge(true);
mDorPresenter.setOnActionClickedListener(new OnActionClickedListener() {
#Override
public void onActionClicked(Action action) {
if (action.getId() == ACTION_UPDATE) {
/*Intent intent = new Intent(getActivity(), PlaybackOverlayActivity.class);
intent.putExtra(getResources().getString(R.string.movie), mSelectedUpdate);
intent.putExtra(getResources().getString(R.string.should_start), true);
startActivity(intent);*/
Toast.makeText(getActivity(), "Download Update", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getActivity(), action.toString(), Toast.LENGTH_SHORT).show();
}
}
});
ps.addClassPresenter(DetailsOverviewRow.class, mDorPresenter);
ps.addClassPresenter(ListRow.class,
new ListRowPresenter());
ArrayObjectAdapter adapter = new ArrayObjectAdapter(ps);
for(DetailsOverviewRow detailRow : detailRows){
adapter.add(detailRow);
}
String subcategories[] = {
getString(R.string.related_movies)
};
//HeaderItem header = new HeaderItem(0, subcategories[0]);
//adapter.add(new ListRow(header, listRowAdapter));
setAdapter(adapter);
}
}
private final class ItemViewClickedListener implements OnItemViewClickedListener {
#Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
if (item instanceof Update) {
Update update = (Update) item;
Log.d(TAG, "Item: " + item.toString());
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtra(DetailsActivity.MOVIE, update);
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
getActivity(),
((ImageCardView) itemViewHolder.view).getMainImageView(),
DetailsActivity.SHARED_ELEMENT_NAME).toBundle();
getActivity().startActivity(intent, bundle);
}
}
}
}
Is there a simple way to add the ProgressBar or do I need to create a completely new xml layout to do this?
I figured out a way to do it. I ended up creating a modified version of lb_details_overview.xml, which is used by the support.v17.leanback library when creating a DetailOverviewRow. I basically just added a RelativeLayout with a ProgressBar. I also had to make a modified version of DetailsOverviewRowPresenter.java in the leanback library in order to inflate the new xml layout instead of the existing one. It might not be the best or the easiest way to do this, but it works.

onClick listener not responding

I was making a project for my class. It's like whac a mole game. I have 9 imageView's in this. As you click on them, they will change to a predefined image of empty hole, if not, the handler will change it back to normal and you will loose a life. But for one picture, if it appears and you click on it, you loose a life. Right now I have fixed the image to be the later one. If I click on them very fast, the textView which shows lives, never gets updated to game over, and tasks continue, but if I click slowly, it gets updated to game over. I tried debugging and found out that when I have clicked on them very quickly, the code never goes to onClick listener.
Here is the code:
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import Hole;
public class MainActivity extends Activity {
final Activity mainActivityObject = this;
final int MIN_TYPES_OF_MOLES = 0;
final int TYPES_OF_MOLES_INC_INT = 1;
final int MAX_MOLE_LIFE_TIME = 3000;
final int LIFE_TIME_DECREASE_INT = 150;
final int MAX_MOLE_APPEARANCE_INT = 1000;
final int APPEARANCE_TIME_DECREASE_INT = 60;
final int SPEED_UP_TIME_INT = 20000;
final int BOMB_MOLE_ID = 3;
final int MIN_DIFFICULTY_LEVEL = 1;
private Toast toast;
final Handler handler = new Handler();
Runnable moleAliveChecker;
Runnable speedUp;
TextView lives;
TextView tView;
//private ImageView[] holeImage = new ImageView[9];
private Hole[] hole = new Hole[9];
private int totalScore = 0;
private int active = 0;
private int numberOfLives = 3;
private int appearanceInterval = MAX_MOLE_APPEARANCE_INT;
private int moleLifeTime = MAX_MOLE_LIFE_TIME;
private int typesOfMoles = MIN_TYPES_OF_MOLES;
private int speedUpTime = SPEED_UP_TIME_INT;
private int difficultyLevel = MIN_DIFFICULTY_LEVEL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// hide the title
setContentView(R.layout.activity_main);
tView = (TextView) findViewById(R.id.time_left);
lives = (TextView) findViewById(R.id.lives_left);
toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_LONG);
//set images and listener for each hole, ends game if lives < 1
for(int counter=0;counter<9;counter++)
{
int resID=getResources().getIdentifier("hole"+(counter+1),"id",getPackageName());
hole[counter] = new Hole((ImageView)findViewById(resID), this);
final int i=counter;//inside the onClickListener, index number has to be final
hole[counter].getImage().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ImageView image = hole[i].getImage();
switch ((Integer) image.getTag()) {
case R.drawable.hole:
break;
default:
if (numberOfLives < 1) {
handler.removeCallbacks(speedUp);
lives.setText("GAME OVER!!");
}
else if (hole[i].getMole().ishit()) {
changeScoreAndLives(hole[i], i);
}
break;
}
}
});
}
// gives a time delay of 3 seconds before beginning the game and updates text view
// tView every 1 second and when time approaches 0, it starts the game
final Runnable r = new Runnable() {
int t = 3;
public void run() {
if (t > 0) {
tView.setText("Game begins in : " + t-- + " Seconds");
handler.postDelayed(this, 1000);
}
else if (t == 0)
{
t--;
tView.setText("Begin!!");
handler.postDelayed(this, 300);
}
else
{
if (numberOfLives >= 1) {
playGame();
handler.postDelayed(this, appearanceInterval);
}
}
}
};
handler.postDelayed(r, 1000);
// speeds up the game after a set interval (20 seconds)
speedUp = new Runnable() {
public void run() {
appearanceInterval -= APPEARANCE_TIME_DECREASE_INT;
moleLifeTime -= LIFE_TIME_DECREASE_INT;
typesOfMoles += TYPES_OF_MOLES_INC_INT;
difficultyLevel++;
if (difficultyLevel < 6 && numberOfLives >= 1) {
handler.postDelayed(this, speedUpTime);
}
toast.setText("Difficulty Level increased");
toast.show();
}
};
handler.postDelayed(speedUp, speedUpTime);
}
// end of onCreate
// not been used yet
private void resetOneStep()
{
if (difficultyLevel > MIN_DIFFICULTY_LEVEL) {
appearanceInterval += MAX_MOLE_APPEARANCE_INT;
moleLifeTime += MAX_MOLE_LIFE_TIME;
typesOfMoles -= MIN_TYPES_OF_MOLES;
difficultyLevel--;
handler.postDelayed(speedUp, speedUpTime);
}
}
// not related to the current problem as currently not being used
public void bombMoleCredit()
{
for (int count = 0; count < hole.length; count++)
if (hole[count].getMole() !=null) {
totalScore += hole[count].getMole().getPoints();
handler.removeCallbacksAndMessages(count);
hole[count].setImage(null, mainActivityObject);
}
tView.setText("Total Score: " + totalScore);
active = 0;
}
// called by onclick listener if lives > 0 to change lives, score, and image
public void changeScoreAndLives(Hole hole, int number)
{
totalScore = totalScore + hole.getMole().getPoints();
if (hole.getMole().getPoints() < 0) {
numberOfLives--;
lives.setText("Lives Left: " + numberOfLives);
}
if (hole.getMole().getID() == BOMB_MOLE_ID) {
bombMoleCredit();
return;
}
handler.removeCallbacksAndMessages(number);
hole.setImage(null, mainActivityObject);
active--;
tView.setText("Total Score: " + totalScore);
}
// called by runnable after a set interval
public void playGame()
{
if (active == 9)
return;
final int holeNumber = (int) (Math.random() * hole.length);
if (hole[holeNumber].getMole() == null && numberOfLives >= 1) {
hole[holeNumber].setMoleFromRange(4, 4, this);
active++;
// checks if the hole has been clicked or not after a few seconds, if not, player
// looses a life
moleAliveChecker = new Runnable() {
Hole holeToBeChecked = hole[holeNumber];
public void run() {
if (holeToBeChecked.getMole() != null && numberOfLives >= 1) {
if(holeToBeChecked.getMole().getID() == 4) {
holeToBeChecked.setImage(null, mainActivityObject);
active--;
return;
}
holeToBeChecked.setImage(null, mainActivityObject);
numberOfLives--;
active--;
TextView lives = (TextView) findViewById(R.id.lives_left);
lives.setText("Lives Left: " + numberOfLives);
toast.setText("OOPS!! you lost a life. Game Reset");
toast.show();
//resetOneStep();
}
}
};
handler.sendMessageDelayed(getPostMessage(moleAliveChecker, holeNumber), moleLifeTime);
}
else
playGame(); // in case the random number choses the image which has the mole
}
// to pass object as a token in postDelayed in handler, to cancel the callbacks
private final Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain(handler, r);
m.obj = token;
return m;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, 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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
All the other classes are working fine except for this one.
Other important classes:
Mole.java
import android.app.Activity;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import java.io.InputStream;
public class Mole
{
public static final int DEFAULT_ID = 0; // regular mole ID
// private methods
private JSONParser parser;
private JSONObject mole;
private int ID, timesToBeHit, timesHit, points;
private String name;
private JSONArray moles;
private boolean active;
public Mole(int ID, Activity map)
{
try {
// initialize and read json and convert each object to jsonArray
parser = new JSONParser();
// tries to set the value set by user. If fails, sets the default value
if (!setMoleByID(ID, map))
setMoleByID(DEFAULT_ID, map);
}
catch (Exception e)
{
e.printStackTrace();
}
}
// helper for constructor
private boolean setMoleByID(int ID, Activity map) throws Exception
{
InputStream is = map.getAssets().open("moles.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String json = new String(buffer, "UTF-8");
moles = (JSONArray)parser.parse(json);
// go through each object in array moles
for ( Object obj : moles)
{
// convert oobject to jsonObject
mole = (JSONObject) obj;
// if id matches it leaves the mole to be that jsonObject and exits
// the loop
if ((long)mole.get("ID") == ID)
break;
}
if ((long)mole.get("ID") != ID)
return false;
// initialize private data so that we don't have to rely on json
// anymore after this step
this.ID = (int)(long)mole.get("ID");
name = (String)mole.get("name");
timesToBeHit = (int)(long)mole.get("timesToBeHit");
timesHit = 0;
points = (int)(long)mole.get("points");
return true;
}
// get methods
public int getID() { return ID; }
public String getName() { return name; }
public int getTimesHit() { return timesHit; }
public int getTimesToBeHit() { return timesToBeHit; }
public int getPoints() { return points; }
public boolean ishit()
{
if (timesHit >= timesToBeHit - 1)
return true;
timesHit++;
return false;
}
public static int getTotalTypesOfMoles() throws Exception
{
return 5;
}
}
Hole.java
import android.app.Activity;
import android.widget.ImageView;
import com.example.phoenix.whac_a_mole03.R;
// NOT completed yet
// HOLE Class -----------------------------------------------------------------
public class Hole
{
private Mole mole;
private boolean active; // if true then mole is present
private ImageView image;
public Hole(ImageView view,final Activity map)
{
mole = null;
image = view;
setImage(mole, map);
}
// sets mole from a random value
public boolean setMoleFromRange(int minMoleID,
int maxMoleID, Activity map)
{
try {
int typesOfMoles = Mole.getTotalTypesOfMoles() - 1;
// checks for validity of data here
if (!(minMoleID >= 0 & minMoleID <= typesOfMoles))
return false;
if (!(maxMoleID >= 0 & maxMoleID <= typesOfMoles))
return false;
if (minMoleID > maxMoleID)
return false;
// chooses the random value between a range
int moleID =
(int) (Math.random() * (maxMoleID + 1 - minMoleID)) + minMoleID;
mole = new Mole(moleID, map);
setImage(mole, map);
return true;
}
catch (Exception e)
{
e.printStackTrace();
}
return false;
}
private void clear()
{
mole = null;
}
public void setImage(Mole mole, Activity map)
{
if (mole == null) {
image.setImageResource(R.drawable.hole);
image.setTag(R.drawable.hole);
clear();
return;
}
int imageID = map.getResources().getIdentifier("mole" + mole.getID() , "drawable", map.getPackageName());
image.setImageResource(imageID);
image.setTag(imageID);
this.mole = mole;
}
public boolean hit(Activity map)
{
if (!mole.ishit())
return false;
setImage(mole, map);
return true;
}
// get methods
public Mole getMole() { return mole; }
public ImageView getImage() { return image;}
// REST STUFF TO BE ADDED HERE-------------
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:id="#+id/time_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/lives_left"
android:layout_alignParentRight="true"
android:text="Lives Left: 3"
android:textAlignment="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<GridLayout
android:columnCount="3"
android:rowCount="3"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/hole1"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole2"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole3"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole4"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole5"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole6"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole7"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole8"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
<ImageView
android:id="#+id/hole9"
android:src="#drawable/hole"
android:layout_width="100dp"
android:layout_height="100dp" />
</GridLayout>
<GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/life1"/>
<ImageView
android:id="#+id/life2"/>
<ImageView
android:id="#+id/life3"/>
</GridLayout>
</RelativeLayout>
Any picture can be used as long as it is named mole4.png and when there is no mmole then hole.png
Thanks a lot. I will appreciate your help

Android: Adding functionality that activty changes when game is complete

I wish to add the following functionality to my game:
-When the game is complete (no more cards are visible on screen) then move to a new activity
I am aware how to move to another activty using intents but I am not sure how to implement the functionality in this case.
I.e. what variable/info can I use to ensure the game is complete when I move before moving to the next activity?
For reference, The game is based off this open source game Images of the game are shown here to give an idea.
Current code:
public class Manager extends Activity {
private static int ROW_COUNT = -1;
private static int COL_COUNT = -1;
private Context context;
private Drawable backImage;
private int [] [] cards;
private List<Drawable> images;
private Card firstCard;
private Card seconedCard;
private ButtonListener buttonListener;
private static Object lock = new Object();
int turns;
private TableLayout mainTable;
private UpdateCardsHandler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new UpdateCardsHandler();
loadImages();
setContentView(R.layout.main);
TextView url = ((TextView)findViewById(R.id.myWebSite));
Linkify.addLinks(url, Linkify.WEB_URLS);
backImage = getResources().getDrawable(R.drawable.icon);
/*
((Button)findViewById(R.id.ButtonNew)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
newGame();
}
});*/
buttonListener = new ButtonListener();
mainTable = (TableLayout)findViewById(R.id.TableLayout03);
context = mainTable.getContext();
Spinner s = (Spinner) findViewById(R.id.Spinner01);
ArrayAdapter adapter = ArrayAdapter.createFromResource(
this, R.array.type, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
s.setOnItemSelectedListener(new OnItemSelectedListener(){
#Override
public void onItemSelected(
android.widget.AdapterView<?> arg0,
View arg1, int pos, long arg3){
((Spinner) findViewById(R.id.Spinner01)).setSelection(0);
int x,y;
switch (pos) {
case 1:
x=4;y=4;
break;
case 2:
x=4;y=5;
break;
case 3:
x=4;y=6;
break;
case 4:
x=5;y=6;
break;
case 5:
x=6;y=6;
break;
default:
return;
}
newGame(x,y);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
private void newGame(int c, int r) {
ROW_COUNT = r;
COL_COUNT = c;
cards = new int [COL_COUNT] [ROW_COUNT];
mainTable.removeView(findViewById(R.id.TableRow01));
mainTable.removeView(findViewById(R.id.TableRow02));
TableRow tr = ((TableRow)findViewById(R.id.TableRow03));
tr.removeAllViews();
mainTable = new TableLayout(context);
tr.addView(mainTable);
for (int y = 0; y < ROW_COUNT; y++) {
mainTable.addView(createRow(y));
}
firstCard=null;
loadCards();
turns=0;
((TextView)findViewById(R.id.tv1)).setText("Tries: "+turns);
}
private void loadImages() {
images = new ArrayList<Drawable>();
images.add(getResources().getDrawable(R.drawable.card1));
images.add(getResources().getDrawable(R.drawable.card2));
images.add(getResources().getDrawable(R.drawable.card3));
images.add(getResources().getDrawable(R.drawable.card4));
images.add(getResources().getDrawable(R.drawable.card5));
images.add(getResources().getDrawable(R.drawable.card6));
images.add(getResources().getDrawable(R.drawable.card7));
images.add(getResources().getDrawable(R.drawable.card8));
images.add(getResources().getDrawable(R.drawable.card9));
images.add(getResources().getDrawable(R.drawable.card10));
images.add(getResources().getDrawable(R.drawable.card11));
images.add(getResources().getDrawable(R.drawable.card12));
images.add(getResources().getDrawable(R.drawable.card13));
images.add(getResources().getDrawable(R.drawable.card14));
images.add(getResources().getDrawable(R.drawable.card15));
images.add(getResources().getDrawable(R.drawable.card16));
images.add(getResources().getDrawable(R.drawable.card17));
images.add(getResources().getDrawable(R.drawable.card18));
images.add(getResources().getDrawable(R.drawable.card19));
images.add(getResources().getDrawable(R.drawable.card20));
images.add(getResources().getDrawable(R.drawable.card21));
}
private void loadCards(){
try{
int size = ROW_COUNT*COL_COUNT;
Log.i("loadCards()","size=" + size);
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0;i<size;i++){
list.add(new Integer(i));
}
Random r = new Random();
for(int i=size-1;i>=0;i--){
int t=0;
if(i>0){
t = r.nextInt(i);
}
t=list.remove(t).intValue();
cards[i%COL_COUNT][i/COL_COUNT]=t%(size/2);
Log.i("loadCards()", "card["+(i%COL_COUNT)+
"]["+(i/COL_COUNT)+"]=" + cards[i%COL_COUNT][i/COL_COUNT]);
}
}
catch (Exception e) {
Log.e("loadCards()", e+"");
}
}
private TableRow createRow(int y){
TableRow row = new TableRow(context);
row.setHorizontalGravity(Gravity.CENTER);
for (int x = 0; x < COL_COUNT; x++) {
row.addView(createImageButton(x,y));
}
return row;
}
private View createImageButton(int x, int y){
Button button = new Button(context);
button.setBackgroundDrawable(backImage);
button.setId(100*x+y);
button.setOnClickListener(buttonListener);
return button;
}
class ButtonListener implements OnClickListener {
#Override
public void onClick(View v) {
synchronized (lock) {
if(firstCard!=null && seconedCard != null){
return;
}
int id = v.getId();
int x = id/100;
int y = id%100;
turnCard((Button)v,x,y);
}
}
private void turnCard(Button button,int x, int y) {
button.setBackgroundDrawable(images.get(cards[x][y]));
if(firstCard==null){
firstCard = new Card(button,x,y);
}
else{
if(firstCard.x == x && firstCard.y == y){
return; //the user pressed the same card
}
seconedCard = new Card(button,x,y);
turns++;
((TextView)findViewById(R.id.tv1)).setText("Tries: "+turns);
TimerTask tt = new TimerTask() {
#Override
public void run() {
try{
synchronized (lock) {
handler.sendEmptyMessage(0);
}
}
catch (Exception e) {
Log.e("E1", e.getMessage());
}
}
};
Timer t = new Timer(false);
t.schedule(tt, 1300);
}
}
}
class UpdateCardsHandler extends Handler{
#Override
public void handleMessage(Message msg) {
synchronized (lock) {
checkCards();
}
}
public void checkCards(){
if(cards[seconedCard.x][seconedCard.y] == cards[firstCard.x][firstCard.y]){
firstCard.button.setVisibility(View.INVISIBLE);
seconedCard.button.setVisibility(View.INVISIBLE);
}
else {
seconedCard.button.setBackgroundDrawable(backImage);
firstCard.button.setBackgroundDrawable(backImage);
}
firstCard=null;
seconedCard=null;
}
}
}
The easiest way to do this would be to check win conditions with an if statement. This should be done in the method when a turn is actually taken which I assume happens in the turnCard() method.
if (winConditionMet) {
displayWinningScreen();
} else if (lossConditionMet) {
displayLosingScreen();
}
If conditions have been met, then call a method which handles wrapping up that screen, and then launching a new activity. For instance you could add a button to the screen with whatever text you wanted, that when pushed, would take the user to the next screen, be it your score screen, replay screen, main menu, or what have you.
Edit: Okay, since this is a game of memory, you could iterate through the cards at the end of every turn taken and check if any card still has its image set to backImage. If there are none left that are set to backImage, you can then end the game with your code inside of the if statement.
Or, instead of using an ArrayList, you could use some form of Map to keep track of if each card has been permanently turned up or not with the boolean value.

Categories

Resources