i am trying to Record Audio on Android with AudioRecord (http://developer.android.com/reference/android/media/AudioRecord.html#stop%28%29). I geared to Android AudioRecord example
My code is the following:
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.os.Environment;
import android.view.ViewGroup;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;
import android.content.Context;
import android.util.Log;
import android.media.MediaRecorder;
import android.media.MediaPlayer;
import de.benediktbock.fft.fft;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import java.io.IOException;
public class MainActivity extends Activity {
private static final String LOG_TAG = "FFTTEST";
private PlayButton mPlayButton = null;
private TextView realTeil = null;
private TextView imgTeil = null;
private fft mFFT = null;
private int channel_config = AudioFormat.CHANNEL_IN_MONO;
private int format = AudioFormat.ENCODING_PCM_16BIT;
private int sampleRate = 8000;
private int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channel_config, format);
private AudioRecord audioInput = null; //new AudioRecord(AudioSource.MIC, sampleSize, channel_config, format, bufferSize);
private short[] audioBuffer = new short[bufferSize];
private Thread readingThread = null;
private boolean isRecording = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout ll = new LinearLayout(this);
mPlayButton = new PlayButton(this);
ll.addView(mPlayButton,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
realTeil = new TextView(this);
ll.addView(realTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
imgTeil = new TextView(this);
ll.addView(imgTeil,new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0));
setContentView(ll);
realTeil.setText("Realteil");
imgTeil.setText("Imaginärteil");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
class PlayButton extends Button {
boolean mStartPlaying = true;
OnClickListener clicker = new OnClickListener() {
public void onClick(View v) {
onPlay(mStartPlaying);
if (mStartPlaying) {
setText("Stop");
} else {
setText("Start");
}
mStartPlaying = !mStartPlaying;
}
};
public PlayButton(Context ctx) {
super(ctx);
setText("Start");
setOnClickListener(clicker);
}
}
private void onPlay(boolean start) {
if (start) {
startRecording();
} else {
stopRecording();
}
}
private void startRecording()
{
//create and start recorder
audioInput = new AudioRecord(AudioSource.MIC, sampleRate, channel_config, format, bufferSize);
audioInput.startRecording();
isRecording = true;
//start reading thread
readingThread = new Thread(new Runnable()
{
#Override
public void run()
{
readAudioToBuffer();
}
},"readAudio Thread");
readingThread.start();
}
private void readAudioToBuffer()
{
while(isRecording)
{
audioInput.read(audioBuffer, 0,bufferSize);
}
audioInput.stop(); // on this point the app crashes (after clicking "stop")
audioInput.release();
audioInput = null;
}
private void stopRecording()
{
isRecording = false;
readingThread = null;
}
}
I can start the recording without any problems. But when i stop the record the app crashes. I've found out that it crashes at the line audioInput.stop().
Does sombody know where the problem is? I have absolutely no idea.
private void stopRecording()
{
isRecording = false;
// readingThread = null;
}
after setting isRecording=false,you are assigning readingThread=null but the thread immidiately can not finish his task. so it leads your app to creashes.
Related
Here's my code under the name of my class VideoList.java. I did change
the version of the APIs - even the Android version - but still have this
problem:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.youtubekids.cartoons.pojo.VideoPojo;
public class VideoList extends ActionBarActivity {
RequestQueue mRequestQueue;
ImageLoader mImageLoader;
LruBitmapCache mLruBitmapCache;
ImageLoader imageLoader;
ListView lvvideos;
String CHANNEL_ID;
String YOUTUBE_URL = "", YOUTUBEAPIKEY = DataManager.YOUTUBE_API_KEY;
String NEXT_PAGE_TOKEN = "";
ProgressDialog progress;
int total = 0;
ArrayList<VideoPojo> videolist = new ArrayList<VideoPojo>();
Custom_Adapter adapter;
boolean loadmore = false;
TextView txtfooter;
private AdView adView;
private static final String AD_UNIT_ID = DataManager.ADMOB_BANNER;
private InterstitialAd interstitial;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_list);
lvvideos = (ListView) findViewById(R.id.lvvideos);
CHANNEL_ID = DataManager.selectedchannelid;
adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId(AD_UNIT_ID);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
LinearLayout ll = (LinearLayout) findViewById(R.id.ad);
ll.addView(adView);
txtfooter = (TextView) findViewById(R.id.txtfooter);
txtfooter.setVisibility(View.GONE);
new loadvideos().execute();
lvvideos.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (lvvideos.getLastVisiblePosition() >= lvvideos.getCount() - 1) {
if (loadmore) {
new loadvideos().execute();
txtfooter.setText(" Loading more videos...");
txtfooter.setVisibility(View.VISIBLE);
} else {
txtfooter.setText("No More Videos");
txtfooter.setVisibility(View.GONE);
}
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
lvvideos.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
DataManager.selectedvideoid = videolist.get(position).getVideoid();
Intent i = new Intent(VideoList.this, YouTubePlayerActivity.class);
startActivity(i);
overridePendingTransition(0, 0);
}
});
getSupportActionBar().setTitle(DataManager.channelname);
// Begin loading your interstitial.
AdRequest adRequest1 = new AdRequest.Builder().build();
interstitial = new InterstitialAd(this);
interstitial.setAdUnitId(DataManager.ADMOB_INTERSTIAL);
interstitial.loadAd(adRequest1);
AdListener adListener = new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
}
#Override
public void onAdClosed() {
super.onAdClosed();
}
};
interstitial.setAdListener(adListener);
}
public void nointernet()
{
new AlertDialog.Builder(this)
.setTitle("Connection Error")
.setMessage("Try Again")
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
new loadvideos().execute();
}
}).create().show();
}
public void displayInterstitial() {
if (interstitial.isLoaded()) {
interstitial.show();
}
}
#Override
public void onBackPressed() {
Intent i = new Intent(VideoList.this, MainActivity.class);
finish();
startActivity(i);
overridePendingTransition(0,0);
}
private class loadvideos extends AsyncTask<Void, Void, Void> {
boolean isconnect = false;
#Override
protected void onPreExecute() {
// Showing progress dialog before sending http request.
if (!loadmore)
{
progress = GoogleProgress.Progressshow(VideoList.this);
progress.show();
}
}
protected Void doInBackground(Void... unused) {
try {
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(),
15000);
HttpConnectionParams.setSoTimeout(client.getParams(), 15000);
if (!loadmore) {
YOUTUBE_URL = "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId="
+ CHANNEL_ID
+ "&maxResults="
+ DataManager.maxResults + "&key=" + YOUTUBEAPIKEY+"&order=date";
} else {
YOUTUBE_URL = "https://www.googleapis.com/youtube/v3/search?part=snippet&pageToken="
+ NEXT_PAGE_TOKEN
+ "&channelId="
+ CHANNEL_ID
+ "&maxResults="
+ DataManager.maxResults
+ "&key="
+ YOUTUBEAPIKEY+"&order=date";
}
HttpUriRequest request = new HttpGet(YOUTUBE_URL);
HttpResponse response = client.execute(request);
InputStream atomInputStream = response.getEntity().getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(
atomInputStream));
String line;
String str = "";
while ((line = in.readLine()) != null) {
str += line;
}
System.out.println("url---" + str);
JSONObject json = new JSONObject(str);
JSONArray items = json.getJSONArray("items");
total = json.getJSONObject("pageInfo").getInt("totalResults");
if (total > 20) {
loadmore = true;
NEXT_PAGE_TOKEN = json.getString("nextPageToken");
}
for (int i = 0; i < items.length(); i++) {
VideoPojo video = new VideoPojo();
JSONObject youtubeObject = items.getJSONObject(i)
.getJSONObject("snippet");
video.setVideoid(items.getJSONObject(i).getJSONObject("id")
.getString("videoId"));
video.setTitle(youtubeObject.getString("title"));
video.setThumbnail(youtubeObject
.getJSONObject("thumbnails").getJSONObject("high")
.getString("url"));
videolist.add(video);
}
isconnect = true;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
isconnect = false;
System.out.println("1exception---" + e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
isconnect = false;
System.out.println("2exception---" + e.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
System.out.println("3exception---" + e.getMessage());
e.printStackTrace();
}
return (null);
}
protected void onPostExecute(Void unused) {
// Closing progress dialog.
progress.dismiss();
if (isconnect) {
if (videolist.size() > 0) {
displayInterstitial();
adapter = new Custom_Adapter(getApplicationContext());
lvvideos.setAdapter(adapter);
if (loadmore)
lvvideos.setSelection(((videolist.size() - DataManager.maxResults)-1));
else
lvvideos.setSelection(0);
if (total > videolist.size()) {
loadmore = true;
}else
{
loadmore = false;
}
}
} else {
nointernet();
}
}
}
public class Custom_Adapter extends BaseAdapter {
private LayoutInflater mInflater;
public Custom_Adapter(Context c) {
mInflater = LayoutInflater.from(c);
imageLoader = getImageLoader(c);
}
#Override
public int getCount() {
return videolist.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row_video_list, null);
holder = new ViewHolder();
holder.txttitle = (TextView) convertView
.findViewById(R.id.txttitle);
holder.img = (FeedImageView) convertView.findViewById(R.id.img);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txttitle.setText("" + videolist.get(position).getTitle());
holder.img.setImageUrl(videolist.get(position).getThumbnail(),
imageLoader);
return convertView;
}
class ViewHolder {
TextView txttitle;
FeedImageView img;
}
}
public RequestQueue getRequestQueue(Context context) {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(context);
}
return mRequestQueue;
}
public ImageLoader getImageLoader(Context context) {
getRequestQueue(context);
if (mImageLoader == null) {
getLruBitmapCache();
mImageLoader = new ImageLoader(mRequestQueue, mLruBitmapCache);
}
return this.mImageLoader;
}
public LruBitmapCache getLruBitmapCache() {
if (mLruBitmapCache == null)
mLruBitmapCache = new LruBitmapCache();
return this.mLruBitmapCache;
}
}
So this is my code.
And when I try to build my apk or debug the project I see the following error:
build failed 1m 1s 703ms Run build 59s 306ms Load build 4s 974ms Run
init scripts 4s 952ms Apply script sync.local.repo293.gradle 4s 951ms
Evaluate settings 6ms Configure build 13s 725ms Calculate task
graph 25s 469ms Run tasks 15s 117ms null
/Users/ismailtaibi/Downloads/fortinvideoappyt-3.1/codecanyon-11481105-fortin-video-channel-app-youtube-api-v3/FortinYoutubeChannelV3AndroidSource app/src/main/java com/youtubekids/cartoons/VideoList.java error:
package org.apache.http does not exist error: package
org.apache.http.client.methods does not exist error: package
org.apache.http.impl.client does not exist error: cannot find symbol
class DefaultHttpClient error: cannot find symbol class HttpGet
You need to add HttpClient as project's dependency. Here you will have details on Grade/Maven dependency that you will have to add to your .build or .pom file
https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient/4.5
This is the MainActivity.java
package com.test.webservertest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.support.v7.app.ActionBarActivity;
import android.util.AndroidRuntimeException;
import android.util.Xml;
import android.view.Menu;
import android.view.MenuItem;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.content.Context;
import android.view.View.OnClickListener;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EncodingUtils;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import java.io.*;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity
{
private static final int MY_DATA_CHECK_CODE = 0;
public static MainActivity currentActivity;
TextToSpeech mTts;
private String targetURL;
private String urlParameters;
private Button btnClick;
private String clicking = "clicked";
private final String[] ipaddresses = new String[2];
private final Integer[] ipports = new Integer[2];
private TextView text;
private Socket socket;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setContentView(new SingleTouchEventView(this, null));
/*ipaddresses[0] = "10.0.0.3";
ipaddresses[1] = "10.0.0.2";
ipports[0] = 8098;
ipports[1] = 8088;*/
//addListenerOnButton();
currentActivity = this;
initTTS();
}
public void addListenerOnButton() {
/*btnClick = (Button) findViewById(R.id.checkipbutton);
btnClick.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
text = (TextView) findViewById(R.id.textView2);
try
{
} catch (Exception e)
{
text.setText("Connection Failed");
}
}
});*/
}
#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);
}
/**
* Dispatch onStart() to all fragments. Ensure any created loaders are
* now started.
*/
#Override
protected void onStart()
{
super.onStart();
TextToSpeechServer.main(null);
}
#Override
protected void onStop() {
super.onStop();
}
public void initTTS() {
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == MY_DATA_CHECK_CODE) {
if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
mTts = new TextToSpeech(getApplicationContext(), new OnInitListener() {
#Override
public void onInit(int i) {
if(i == TextToSpeech.SUCCESS) {
int result = mTts.setLanguage(Locale.US);
if(result == TextToSpeech.LANG_AVAILABLE
|| result == TextToSpeech.LANG_COUNTRY_AVAILABLE) {
mTts.setPitch(1);
mTts.speak(textforthespeacch, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
});
} else {
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
public static String textforthespeacch = "";
public static void TextToSpeak(String text) {
textforthespeacch = text;
}
private boolean is_start = true;
public class SingleTouchEventView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private Path circlePath = new Path();
public SingleTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(6f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawPath(path, paint);
canvas.drawPath(circlePath, paint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
float lastdownx = 0;
float lastdowny = 0;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
circlePath.addCircle(eventX, eventY, 50, Path.Direction.CW);
lastdownx = eventX;
lastdowny = eventY;
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
byte[] response = null;
if (is_start == true)
{
response = Get("http://10.0.0.2:8098/?cmd=start");
is_start = false;
}
else
{
response = Get("http://10.0.0.2:8098/?cmd=stop");
is_start = true;
}
if (response!=null)
{
String a = null;
try
{
a = new String(response,"UTF-8");
textforthespeacch = a;
MainActivity.currentActivity.initTTS();
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
Logger.getLogger("MainActivity(inside thread)").info(a);
}
}
});
t.start();
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
// nothing to do
circlePath.reset();
break;
default:
return false;
}
// Schedules a repaint.
invalidate();
return true;
}
}
private byte[] Get(String urlIn)
{
URL url = null;
String urlStr = urlIn;
if (urlIn!=null)
urlStr=urlIn;
try
{
url = new URL(urlStr);
} catch (MalformedURLException e)
{
e.printStackTrace();
return null;
}
HttpURLConnection urlConnection = null;
try
{
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
byte[] buf=new byte[10*1024];
int szRead = in.read(buf);
byte[] bufOut;
if (szRead==10*1024)
{
throw new AndroidRuntimeException("the returned data is bigger than 10*1024.. we don't handle it..");
}
else
{
bufOut = Arrays.copyOf(buf, szRead);
}
return bufOut;
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
finally
{
if (urlConnection!=null)
urlConnection.disconnect();
}
}
}
It was working fine. Maybe I need to enable something on my Android device?
My Android device is connected now to the PC via USB and working fine.
When I'm running my program in debug mode and touch the screen it never stop on:
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
I added a break point on the line: float eventX = event.getX();
But touching the screen does nothing.
You are not at all registering the OnTouchListener. First register OnTouchListener using anonymousclass or just implements it in your class
From your code you need the listener for this SingleTouchEventView view. Just add "implements View.OnTouchListenter" for the class. Because you have already overridden onTouch method in your code.
You have to change your style.xml when you remove "Extends ActionbarActivity"!
Check this change appTheme
There is a problem with the code for android applications
I tried to assign multiple actions to a single button.Here's the code:
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
AudioRecord audioRecord;
private Thread recordingThread = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
start_button = (Button) findViewById(R.id.button1);
stop_button = (Button) findViewById(R.id.button2);
start_button.setOnClickListener(this);
stop_button.setOnClickListener(this);
createAudioRecorder();
}
private void createAudioRecorder() {
int sampleRate = 16000;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int minInternalBufferSize = AudioRecord.getMinBufferSize(sampleRate,
channelConfig, audioFormat);
int internalBufferSize = minInternalBufferSize * 4;
Log.d(TAG, "minInternalBufferSize = " + minInternalBufferSize
+ ", internalBufferSize = " + internalBufferSize
+ ", myBufferSize = " + myBufferSize);
audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRate, channelConfig, audioFormat, internalBufferSize);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
reading = true;
startRecorder();
break;
case R.id.button2:
reading = false;
stopRecorder();
break;
}
}
private void startRecorder() {
recordingThread = new Thread(new Runnable() {
#Override
public void run() {
AudioData();
}
}, "AudioRecorder Thread");
recordingThread.start();
}
protected void AudioData() {
audioRecord.startRecording();
byte data[] = new byte[myBufferSize];
byte[] myBuffer = new byte[myBufferSize];
int readCount = 0;
int totalCount = 0;
while (reading) {
readCount = audioRecord.read(myBuffer, 0, myBufferSize);
data = myBuffer;
totalCount += readCount;
}
}
private void stopRecorder() {
if (null != audioRecord) {
reading = false;
audioRecord.stop();
audioRecord.release();
audioRecord = null;
recordingThread = null;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
When I run this code the first time it works, but not following..
Logs show that the error here somewhere (NullPointerException):
audioRecord.startRecording();
Help solve the problem!
When button2 is clicked, stopRecorder() is called, which assigns null to audioRecord. Therefore, the next time button1 is clicked, the new thread that is spawned will throw a NullPointerException when it calls AudioData().
Perhaps you can eliminate createAudioRecorder() and move its logic to the beginning of AudioData().
Also, I would rename AudioData(), which looks like a class name, to recordAudioData(). That would conform better to standard Java naming conventions.
I have an app that uses a system of plugins. These "plugins" send out a broadcast message which my app then receives and uses the relevant data attached to register the app.
The issues is that I dont know how many plugin are installed on the device at any given time, so I dont know how many messages to wait for, and I don't know of any way to check to see if its the last message being sent.
Right now I'm kinding faking it by waiting for a three second timer to finish, allowing three seconds for the plugins to register, but as more plugins are developed, this isnt going to be enough time.
How can I refresh my UI only when all of the plugins have finished registering?
PanelReceiver.java
package com.t3hh4xx0r.haxlauncher.menu.livepanel;
import java.io.ByteArrayOutputStream;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import com.t3hh4xx0r.haxlauncher.DBAdapter;
public class PanelReceiver extends BroadcastReceiver {
private static final String PANEL_REQUEST = "com.t3hh4xx0r.haxlauncher.PANEL_REQUEST";
private static final String PANEL_REGISTER = "com.t3hh4xx0r.haxlauncher.PANEL_REGISTER";
private static final String PANEL_UPDATE = "com.t3hh4xx0r.haxlauncher.PANEL_UPDATE";
boolean shouldAdd = true;
#Override
public void onReceive(Context context, Intent intent) {
String a = intent.getAction();
if (a.equals(PANEL_REGISTER)) {
Bundle b = intent.getExtras();
String author = b.getString("author_name");
String plugin = b.getString("plugin_name");
String packageN = b.getString("package_name");
String desc = b.getString("description");
String version = b.getString("version");
DBAdapter db = new DBAdapter(context);
db.open();
Cursor c = db.getAllPanels();
if (c.getCount() != 0) {
while (c.moveToNext()) {
if (c.getString(c.getColumnIndex("author")).equals(author) &&
c.getString(c.getColumnIndex("package")).equals(packageN)){
shouldAdd = false;
if (!c.getString(c.getColumnIndex("version")).equals(version)) {
db.removePanel(packageN);
shouldAdd = true;
}
}
}
}
if (shouldAdd) {
db.insertPanel(version, author, plugin, packageN, desc, image("ic_launcher", context, packageN), image("screencap", context, packageN));
}
db.close();
} else if (a.equals(PANEL_UPDATE)) {
Log.d("UPDATE", "OMFG!");
}
}
public static void requestPanels(Context context) {
Intent i = new Intent();
i.setAction(PANEL_REQUEST);
context.sendBroadcast(i);
}
public byte[] image(String imageName, Context c, String packageN) {
try {
Context fC = c.getApplicationContext().createPackageContext(packageN, Context.CONTEXT_IGNORE_SECURITY);
Resources res = fC.getResources();
Bitmap photo = drawableToBitmap(res.getDrawable(res.getIdentifier(imageName, "drawable", packageN)));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, bos);
return bos.toByteArray();
} catch (NameNotFoundException e) {
return null;
}
};
public static Bitmap drawableToBitmap (Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable)drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
PanelMenuActivity.java
package com.t3hh4xx0r.haxlauncher.menu.livepanel;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import com.t3hh4xx0r.haxlauncher.DBAdapter;
import com.t3hh4xx0r.haxlauncher.R;
public class PanelMenuActivity extends Activity {
ListView lv;
static ArrayAdapter<String> a;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.panel_menu);
lv = (ListView) findViewById(R.id.panel_list);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int pos,
long id) {
Intent i = new Intent(v.getContext(), PanelDetails.class);
Bundle b = new Bundle();
b.putInt("pos", ((PanelDetailHolder)a.getItemAtPosition(pos)).id);
i.putExtras(b);
startActivity(i);
}
});
GetPanelsTask t = new GetPanelsTask();
t.execute();
}
private ListAdapter buildAdapter(Context c) {
return new PanelAdapter(this, getPanels(c));
}
public ArrayList<PanelDetailHolder> getPanels(Context ctx) {
ArrayList<PanelDetailHolder> panelArray = new ArrayList<PanelDetailHolder>();
DBAdapter db = new DBAdapter(ctx);
db.open();
Cursor c = db.getAllPanels();
while (c.moveToNext()) {
try{
getPackageManager().getApplicationInfo(c.getString(c.getColumnIndex("package")), 0 );
} catch (NameNotFoundException e){
db.removePanel(c.getString(c.getColumnIndex("package")));
continue;
}
PanelDetailHolder p = new PanelDetailHolder();
p.author = c.getString(c.getColumnIndex("author"));
p.title = c.getString(c.getColumnIndex("name"));
p.desc = c.getString(c.getColumnIndex("desc"));
p.version = c.getString(c.getColumnIndex("version"));
p.id = c.getPosition();
panelArray.add(p);
}
c.close();
db.close();
return panelArray;
}
#Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.refresh:
GetPanelsTask t = new GetPanelsTask();
t.execute();
}
return false;
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuinflate = new MenuInflater(this);
menuinflate.inflate(R.menu.panel_menu, menu);
return true;
}
public class GetPanelsTask extends AsyncTask<Object, View, Void> {
ProgressDialog progressDialog;
#Override
protected void onPreExecute() {
progressDialog= ProgressDialog.show(PanelMenuActivity.this,
"Loading...","Checking for live panels...", true);
PanelReceiver.requestPanels(PanelMenuActivity.this);
};
#Override
protected Void doInBackground(Object... params) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
};
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
progressDialog.dismiss();
lv.setAdapter(buildAdapter(PanelMenuActivity.this));
}
}
class PanelDetailHolder {
String author;
String title;
String desc;
String version;
Drawable screenCap;
Drawable icon;
int id;
}
}
How can I refresh my UI only when all of the plugins have finished registering?
By definition, it is not possible. You need to revise your plugin system so that either:
You "know how many plugin are installed on the device", or
You do not need to wait (or even really care) at any point "how many plugin are installed on the device"
It's the usual activity. The problem is in onCreateOptionMenu. When I click the menu button nothing is done. I don't see where the problem is.
I also try to comment all code without menu but It's still don't work.
It is either a very strange problem or I don't see some simple things..
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.LinearLayout;
public class Izu4aikaActivity extends Activity implements OnClickListener {
public final int INFO = 101;
public final int BLOCK = 102;
public final int CLOSE = 103;
final String sdDir = Environment.getExternalStorageDirectory()+"/izuchaika/";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// Thread to write files to SD
final String file = "Files";
File dir = new File(sdDir);
dir.mkdir();
dir.mkdirs();
new Thread(new Runnable() {
public void run() {
copyFileOrDir(file);
}
}).start();
LinearLayout ll = (LinearLayout) findViewById(R.id.main_layout);
ll.setOnClickListener(this);
}
//Menu
public boolean onCreateOptionMenu(Menu menu) {
menu.add(Menu.NONE, INFO, Menu.NONE, "О программе").setIcon(
R.drawable.info);
menu.add(Menu.NONE, BLOCK, Menu.NONE, "Блокировать").setIcon(
R.drawable.block);
menu.add(Menu.NONE, CLOSE, Menu.NONE, "Выход").setIcon(R.drawable.exit);
return super.onCreateOptionsMenu(menu);
}
#Override
public void onClick(View v) {
Intent i = new Intent(this, mScr.class);
startActivity(i);
}
private void copyFileOrDir(String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path);
} else {
String fullPath = sdDir + path;
File dir = new File(fullPath);
if (!dir.exists())
dir.mkdir();
for (int i = 0; i < assets.length; ++i) {
copyFileOrDir(path + "/" + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String filename) {
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
String newFileName = sdDir + filename;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
}
Help if you see a solution.
You've misspelled method name - it should be onCreateOptionsMenu(), not onCreateOptionMenu().
It's preferable to use #Override annotation to avoid such mistakes:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
This way it will give you compile time error if you misspell method name or use wrong parameters.
Change your onCreateOptionsMenu to:
//Menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, INFO, Menu.NONE, "О программе").setIcon(
R.drawable.info);
menu.add(Menu.NONE, BLOCK, Menu.NONE, "Блокировать").setIcon(
R.drawable.block);
menu.add(Menu.NONE, CLOSE, Menu.NONE, "Выход").setIcon(R.drawable.exit);
return true;
}
It should work now!
try to add
#Override to public boolean onCreateOptionMenu
And do you try to use MenuInflater and inflate menu from xml?