Mediarecorder on Android 4.2 - invalid state exception - java

I'm trying to record calls using media record. Recording on android 5 works perfectly but on android 4.2 I get Invalid state exception in recorder.start()
I have defined persmissions as: READ_PHONE_STATE, RECORD_VIDEO, RECORD_AUDIO
Anyone helps?
Code of my broadcast receiver:
public class PhoneStateChangeReceiver extends BroadcastReceiver {
//The receiver will be recreated whenever android feels like it. We need a static variable to remember data between instantiations
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
private static MediaRecorder recorder;
private static long RecordingStartedTime = 0;
private static Context Context;
private static Configuration Config;
private static boolean Recording = false;
public void dropRecording() {
try {
Recording = false;
long EndTime = System.currentTimeMillis();
long Duration = EndTime - callStartTime.getTime();
// record to database
FileRecords fileRecords = new FileRecords(Context);
fileRecords.record(callStartTime.getTime(),
EndTime,
Duration,
Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp",
0,
FileRecords.TYPE.THREEGP,
savedNumber);
if(recorder != null) {
recorder.stop();
recorder.release();
}
} catch (Exception e) {
Logs.Put(e, Context);
}
}
private void StartRecording() {
try {
RecordingStartedTime = System.currentTimeMillis();
try {
recorder.stop();
recorder.reset();
recorder.release();
} catch(Exception e) {
}
recorder = new MediaRecorder();
String FileName = Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp";
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioChannels(1);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(FileName);
recorder.setMaxFileSize(Config.MaxRecordFileSize() * 1024 * 1024);
recorder.setMaxDuration(Config.MaxRecordTime());
recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
dropRecording();
}
});
recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED || what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
dropRecording();
}
}
});
recorder.setAudioEncodingBitRate(Config.AudioBitRateQuality());
recorder.prepare();
recorder.start();
Recording = true;
} catch (Exception e) {
Logs.Put(e, Context);
try {
RecordingStartedTime = System.currentTimeMillis();
try {
recorder.stop();
recorder.reset();
recorder.release();
} catch(Exception ex) {
}
recorder = new MediaRecorder();
String FileName = Context.getFilesDir() + "/" + RecordingStartedTime + ".3gp";
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioChannels(1);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(FileName);
recorder.setMaxFileSize(Config.MaxRecordFileSize() * 1024 * 1024);
recorder.setMaxDuration(Config.MaxRecordTime());
recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
dropRecording();
}
});
recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED || what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
Logs.Put("mediarecorder error:" + Integer.toString(what) + " extra" + Integer.toString(extra), Context);
dropRecording();
}
}
});
recorder.setAudioEncodingBitRate(Config.AudioBitRateQuality());
recorder.prepare();
recorder.start();
Recording = true;
} catch (Exception ex) {
Logs.Put(ex, Context);
}
}
}
#Override
public void onReceive(Context context, Intent intent) {
Context = context;
Config = new Configuration(context);
if(!Config.RecordCalls())
return;
//We listen to two intents. The new outgoing call only tells us of an outgoing call. We use it to get the number.
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start){
StartRecording();
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start){
StartRecording();
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){
dropRecording();
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end){
dropRecording();
}
protected void onMissedCall(Context ctx, String number, Date start){
// do nothing;
}
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// ringing do nothing
savedNumber = number;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
} else {
isIncoming = true;
callStartTime = new Date();
onIncomingCallStarted(context, number, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}

Related

Start Service in BroadCastReceiver android 8

I want to Start a long time Service which observes the android Downloads folder ,
I have created a BroadcastReceiver which receives the BOOT_COMPLETED event and this BroadcastReceiver will start the Service using context.startStartService() method.
It seems the way it is working correct in android versions below 8 but for higher versions of android I get an error which is
android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{ba36f7 u0 packagename/.FileSystemObserverService}
StartupBroadCastReceiver
public class StartupReceiver extends BroadcastReceiver {
private static final String TAG = "StartupReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "onReceive: called " );
appendLog(context,"OnReceived called StartupReceive line 20");
Toast.makeText(context, "Boot Completed", Toast.LENGTH_SHORT).show();
Intent myIntent = new Intent(context, FileSystemObserverService.class);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
context.startForegroundService(myIntent);
return;
}
context.startService(myIntent);
}
private void appendLog(Context context,String log){
SharedPreferences sp = context.getSharedPreferences("sp",Context.MODE_PRIVATE);
String preLogs = sp.getString("logs","");
preLogs+="\n"+log;
sp.edit().putString("logs",preLogs).apply();
}
}
Above code is my BroadcastReceiver which receives BOOT_COMPLETED event.
FileSystemObserver
public class FileSystemObserverService extends Service {
private Observer mMainObserver;
private static final String TAG = "FileSystemObserverServi";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: get called " );
observe();
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: called for fileObserverService");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void observe(){
Thread t= new Thread(new Runnable() {
#Override
public void run() {
Log.e(TAG, "run: thread is running " );
File str = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
if (str!=null){
Log.e(TAG, "run: "+str.getAbsolutePath());
String downloadsPath = str.getAbsolutePath();
mMainObserver= new Observer(downloadsPath, new DataInterface() {
#Override
public String getMacAddress() {
SharedPreferences sp = getSharedPreferences("sp",MODE_PRIVATE);
return sp.getString("mac_address",null);
}
#Override
public void appendLog(String log) {
SharedPreferences sp = getSharedPreferences("sp",MODE_PRIVATE);
String preLogs = sp.getString("logs","");
preLogs+="\n"+log;
sp.edit().putString("logs",preLogs).apply();
}
});
mMainObserver.startWatching();
}
}
});
t.setPriority(Thread.MIN_PRIORITY);
t.start();
}
}
interface DataInterface{
public String getMacAddress();
public void appendLog(String log);
}
class Observer extends FileObserver{
private static final String TAG = "Observer";
List<SingleFileObserver> mObserves;
String mPath;
int mMask;
Context mContext;
private SendPDF sendPDF;
private DataInterface di ;
public Observer(String path,DataInterface di) {
this(path,ALL_EVENTS);
this.di = di;
}
#Override
public void startWatching() {
Log.e(TAG, "startWatching: getCalled" );
di.appendLog("Line 104 FileSystemObserverService startWatching : called");
try{
if(mObserves!=null)
return;
mObserves = new ArrayList<SingleFileObserver>();
Stack<String> stack = new Stack<String>();
stack.push(mPath);
while (!stack.isEmpty()){
String parent = stack.pop();
mObserves.add(new SingleFileObserver(parent,mMask));
File path = new File(parent);
File[] files = path.listFiles();
if (files==null) continue;
}
for (SingleFileObserver ob : mObserves){
ob.startWatching();
}
}catch (Exception e){
di.appendLog("Line 124 FileSystemObserverService "+e.getMessage());
}
}
#Override
public void stopWatching() {
if (mObserves==null)
return;
for (SingleFileObserver ob : mObserves){
ob.stopWatching();
}
mObserves.clear();
mObserves = null;
}
public Observer(String path , int mask){
super(path,mask);
mPath = path;
mMask = mask;
}
public String getReadableEventName(int e ){
switch (e){
case FileObserver.OPEN:
return "OPEN";
case FileObserver.CREATE:
return "CREATE";
case DELETE_SELF:
return "DELETE_SELF";
case DELETE :
return "DELETE";
case MOVED_FROM :
return "MOVED_FROM";
case MOVED_TO:
return "MOVED_TO";
case MOVE_SELF:
return "MOVED_SELF";
default:
return "UNKNOWN";
}
}
#Override
public void onEvent(int event, #Nullable String path) {
// if (mContext!=null)
// Toast.makeText(mContext, "Event Called " +path, Toast.LENGTH_SHORT).show();
Log.e(TAG, "onEvent: Called "+path);
di.appendLog("Line 157 FileSystemObserverService onEventCalled with " +event+" name: " +getReadableEventName(event)+ " path: "+path);
try{
switch (event){
case FileObserver.OPEN:
Log.e(TAG, "onEvent: OPEN" );
break;
case FileObserver.CREATE:
Log.e(TAG, "onEvent: CREATE");
if (path!=null) {
File file = new File(path);
if (file.isDirectory())
return;
if (!path.endsWith(".pdf"))
return;
sendPDF = new SendPDF(path,di.getMacAddress(),di);
di.appendLog("Line 200 FileSystemObserverService SendPdf instantiated and trying to execute");
sendPDF.execute();
}
break;
case DELETE_SELF:
case DELETE :
Log.e(TAG, "onEvent: DELETE");
break;
case MOVED_FROM :
case MOVED_TO:
case MOVE_SELF:
Log.e(TAG, "onEvent: MOVE");
break;
default:
}
}catch (Exception e){
di.appendLog( "Line 215 FileSystemObserverService "+e.getMessage());
}
}
private class SingleFileObserver extends FileObserver{
private String mPath ;
public SingleFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
}
#Override
public void onEvent(int event, #Nullable String path) {
try{
String newPath = mPath+"/"+path;
Observer.this.onEvent(event,newPath);
Log.e(TAG, "onEvent: "+newPath);
}catch (Exception e){
Log.e(TAG, "onEvent: "+e.getMessage());
}
}
}
}

HOW TO ADD TOAST MESSAGE IN onComplete,I am a begginer in Android Studio and I do not much know about java [duplicate]

This question already has answers here:
Can't toast on a thread that has not called Looper.prepare()
(4 answers)
Closed 2 years ago.
I want to show Toast message in my app after finishing the downloading. I took the code on the internet and it works like this:- the app is downloading the video from the server and after that, it adds my own watermark in the video, it works nicely but now I want to show TOAST message after finishing the adding watermark thing. I add a simple Toast code but after finishing the watermark processing app but it automatically closes because of the simple Toast message, so anyone help to fix his coding problem, if you need any additional info than this, then let me know.
THIS IS THE WHOLE CODE OF MY JAVA CLASS
public class DownloadService extends Service {
private DatabaseHandler db;
private NotificationCompat.Builder myNotify;
private String video_id, downloadUrl, file_path_delete, file_path, file_name, layout_type, watermark_image, watermark_on_off;
private RemoteViews rv;
private OkHttpClient client;
private WaterMarkData waterMarkData;
private GPUMp4Composer gpuMp4Composer;
public static final String ACTION_STOP = "com.mydownload.action.STOP";
public static final String ACTION_START = "com.mydownload.action.START";
private String NOTIFICATION_CHANNEL_ID = "download_ch_1";
private static final String CANCEL_TAG = "c_tag";
NotificationManager mNotificationManager;
private boolean isWaterMark = false;
private boolean isResize = false;
private Handler mHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message message) {
int progress = Integer.parseInt(message.obj.toString());
switch (message.what) {
case 1:
rv.setTextViewText(R.id.nf_title, getString(R.string.app_name));
rv.setProgressBar(R.id.progress, 100, progress, false);
if (isWaterMark) {
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.watermark) + " " + "(" + progress + " %)");
} else {
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.downloading) + " " + "(" + progress + " %)");
}
myNotify.setCustomContentView(rv);
startForeground(1002, myNotify.build());
break;
case 2:
stopForeground(true);
stopSelf();
break;
}
return false;
}
});
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
db = new DatabaseHandler(getApplicationContext());
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
myNotify = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
myNotify.setChannelId(NOTIFICATION_CHANNEL_ID);
myNotify.setSmallIcon(R.mipmap.ic_launcher);
myNotify.setTicker(getResources().getString(R.string.downloading));
myNotify.setWhen(System.currentTimeMillis());
myNotify.setOnlyAlertOnce(true);
rv = new RemoteViews(getPackageName(),
R.layout.my_custom_notification);
rv.setTextViewText(R.id.nf_title, getString(R.string.app_name));
rv.setProgressBar(R.id.progress, 100, 0, false);
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.downloading) + " " + "(0%)");
Intent closeIntent = new Intent(this, DownloadService.class);
closeIntent.setAction(ACTION_STOP);
PendingIntent pcloseIntent = PendingIntent.getService(this, 0,
closeIntent, 0);
rv.setOnClickPendingIntent(R.id.nf_close, pcloseIntent);
myNotify.setCustomContentView(rv);
NotificationChannel mChannel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Online Channel download";// The user-visible name of the channel.
mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(mChannel);
}
startForeground(1002, myNotify.build());
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent.getAction() != null && intent.getAction().equals(ACTION_START)) {
video_id = intent.getStringExtra("video_id");
downloadUrl = intent.getStringExtra("downloadUrl");
file_path = intent.getStringExtra("file_path");
file_name = intent.getStringExtra("file_name");
layout_type = intent.getStringExtra("layout_type");
watermark_image = intent.getStringExtra("watermark_image");
watermark_on_off = intent.getStringExtra("watermark_on_off");
assert watermark_on_off != null;
if (watermark_on_off.equals("true")) {
file_path = getExternalCacheDir().getAbsolutePath();
}
file_path_delete = file_path;
init();
}
if (intent.getAction() != null && intent.getAction().equals(ACTION_STOP)) {
stopForeground(true);
stopSelf();
if (gpuMp4Composer != null) {
gpuMp4Composer.cancel();
}
if (waterMarkData != null) {
waterMarkData.cancel(true);
}
if (!db.checkId_video_download(video_id)) {
db.delete_video_download(video_id);
}
File file = new File(file_path_delete, file_name);
if (file.exists()) {
file.delete();
}
Method.isDownload = true;
if (client != null) {
for (Call call : client.dispatcher().runningCalls()) {
if (call.request().tag().equals(CANCEL_TAG))
call.cancel();
}
}
}
return START_STICKY;
}
public void init() {
new Thread(new Runnable() {
#Override
public void run() {
client = new OkHttpClient();
Request.Builder builder = new Request.Builder()
.url(downloadUrl)
.addHeader("Accept-Encoding", "identity")
.get()
.tag(CANCEL_TAG);
Call call = client.newCall(builder.build());
call.enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
Log.e("TAG", "=============onFailure===============");
e.printStackTrace();
Log.d("error_downloading", e.toString());
Method.isDownload = true;
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
Log.e("TAG", "=============onResponse===============");
Log.e("TAG", "request headers:" + response.request().headers());
Log.e("TAG", "response headers:" + response.headers());
assert response.body() != null;
final ResponseBody responseBody = ProgressHelper.withProgress(response.body(), new ProgressUIListener() {
//if you don't need this method, don't override this methd. It isn't an abstract method, just an empty method.
#Override
public void onUIProgressStart(long totalBytes) {
super.onUIProgressStart(totalBytes);
Log.e("TAG", "onUIProgressStart:" + totalBytes);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.downloading), Toast.LENGTH_SHORT).show();
}
#Override
public void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) {
Log.e("TAG", "=============start===============");
Log.e("TAG", "numBytes:" + numBytes);
Log.e("TAG", "totalBytes:" + totalBytes);
Log.e("TAG", "percent:" + percent);
Log.e("TAG", "speed:" + speed);
Log.e("TAG", "============= end ===============");
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = (int) (100 * percent) + "";
mHandler.sendMessage(msg);
}
//if you don't need this method, don't override this method. It isn't an abstract method, just an empty method.
#Override
public void onUIProgressFinish() {
super.onUIProgressFinish();
Log.e("TAG", "onUIProgressFinish:");
if (watermark_on_off.equals("true")) {
//call data watermark class add to watermark
waterMarkData = new WaterMarkData();
waterMarkData.execute();
} else {
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
showMedia(file_path, file_name);
}
}
});
try {
BufferedSource source = responseBody.source();
File outFile = new File(file_path + "/" + file_name);
BufferedSink sink = Okio.buffer(Okio.sink(outFile));
source.readAll(sink);
sink.flush();
source.close();
} catch (Exception e) {
Log.d("show_data", e.toString());
}
}
});
}
}).start();
}
#SuppressLint("StaticFieldLeak")
class WaterMarkData extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... strings) {
//check water mark on or off
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(downloadUrl);
mp.prepareAsync();
mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.d("call_data", "sizedata");
if (layout_type.equals("Portrait")) {
if (height <= 700) {
isResize = true;
}
} else {
if (height <= 400 || width <= 400) {
isResize = true;
}
}
watermark();//call method water mark adding
}
});
} catch (IllegalArgumentException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (SecurityException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (IllegalStateException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (IOException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (Exception e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d("data", "execute");
}
}
private void watermark() {
//check water mark on or off
new Thread(new Runnable() {
#Override
public void run() {
Bitmap image = null;
try {
URL url = new URL(watermark_image);
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (Exception e) {
Log.d("error_data", e.toString());
}
} catch (IOException e) {
Log.d("error", e.toString());
System.out.println(e);
image = BitmapFactory.decodeResource(getResources(), R.drawable.watermark);
}
if (isResize) {
image = getResizedBitmap(image, 40, 40);
isResize = false;
}
String destinationPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Latest_Video_Status/";
file_path_delete = destinationPath;
gpuMp4Composer = new GPUMp4Composer(file_path + "/" + file_name, destinationPath + file_name)
.filter(new GlWatermarkFilter(image, GlWatermarkFilter.Position.RIGHT_BOTTOM))
.listener(new GPUMp4Composer.Listener() {
#Override
public void onProgress(double progress) {
isWaterMark = true;
double value = progress * 100;
int i = (int) value;
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = i + "";
mHandler.sendMessage(msg);
Log.d(TAG, "onProgress = " + progress);
Log.d("call_data", "watermark");
}
#Override
public void onCompleted() {
isWaterMark = false;
new File(getExternalCacheDir().getAbsolutePath() + "/" + file_name).delete();//delete file to save in cash folder
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
showMedia(destinationPath, file_name);
Log.d(TAG, "onCompleted()");
runOnUiThread(new Runnable()
{
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Your text.",
Toast.LENGTH_SHORT).show();
}
}
);
}
#Override
public void onCanceled() {
isWaterMark = false;
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
Log.d(TAG, "onCanceled");
}
#Override
public void onFailed(Exception exception) {
isWaterMark = false;
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
Log.e(TAG, "onFailed()", exception);
}
})
.start();
}
}).start();
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
public void showMedia(String file_path, String file_name) {
try {
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{file_path + "/" + file_name},
null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
ERROR
Can't toast on a thread that has not called Looper.prepare()
How what to do now to fix this issue, please anyone help me.
Solution
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "KISHAN",
Toast.LENGTH_SHORT).show();
}
});
Add the following line in onCompleted():-
Toast toast = Toast.makeText(getApplicationContext(),
"The text you want to show",
Toast.LENGTH_SHORT
);
If that doesn't work, then let me know.
Edit :-
Working code:-
private DatabaseHandler db;
private NotificationCompat.Builder myNotify;
private String video_id, downloadUrl, file_path_delete, file_path, file_name, layout_type, watermark_image, watermark_on_off;
private RemoteViews rv;
private OkHttpClient client;
private WaterMarkData waterMarkData;
private GPUMp4Composer gpuMp4Composer;
public static final String ACTION_STOP = "com.mydownload.action.STOP";
public static final String ACTION_START = "com.mydownload.action.START";
private String NOTIFICATION_CHANNEL_ID = "download_ch_1";
private static final String CANCEL_TAG = "c_tag";
NotificationManager mNotificationManager;
private boolean isWaterMark = false;
private boolean isResize = false;
public class ServiceHandler {
private final Activity mactivity;
public ServiceHandler(Activity activity)
{
mActivity = activity;
}
public void run() {
<Your Activity Name>.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast toast = Toast.makeText(getApplicationContext(), "Your text", Toast.LENGTH_SHORT).show();
}
});
}
}
private Handler mHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message message) {
int progress = Integer.parseInt(message.obj.toString());
switch (message.what) {
case 1:
rv.setTextViewText(R.id.nf_title, getString(R.string.app_name));
rv.setProgressBar(R.id.progress, 100, progress, false);
if (isWaterMark) {
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.watermark) + " " + "(" + progress + " %)");
} else {
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.downloading) + " " + "(" + progress + " %)");
}
myNotify.setCustomContentView(rv);
startForeground(1002, myNotify.build());
break;
case 2:
stopForeground(true);
stopSelf();
break;
}
return false;
}
});
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
db = new DatabaseHandler(getApplicationContext());
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
myNotify = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
myNotify.setChannelId(NOTIFICATION_CHANNEL_ID);
myNotify.setSmallIcon(R.mipmap.ic_launcher);
myNotify.setTicker(getResources().getString(R.string.downloading));
myNotify.setWhen(System.currentTimeMillis());
myNotify.setOnlyAlertOnce(true);
rv = new RemoteViews(getPackageName(),
R.layout.my_custom_notification);
rv.setTextViewText(R.id.nf_title, getString(R.string.app_name));
rv.setProgressBar(R.id.progress, 100, 0, false);
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.downloading) + " " + "(0%)");
Intent closeIntent = new Intent(this, DownloadService.class);
closeIntent.setAction(ACTION_STOP);
PendingIntent pcloseIntent = PendingIntent.getService(this, 0,
closeIntent, 0);
rv.setOnClickPendingIntent(R.id.nf_close, pcloseIntent);
myNotify.setCustomContentView(rv);
NotificationChannel mChannel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Online Channel download";// The user-visible name of the channel.
mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
mNotificationManager.createNotificationChannel(mChannel);
}
startForeground(1002, myNotify.build());
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (intent.getAction() != null && intent.getAction().equals(ACTION_START)) {
video_id = intent.getStringExtra("video_id");
downloadUrl = intent.getStringExtra("downloadUrl");
file_path = intent.getStringExtra("file_path");
file_name = intent.getStringExtra("file_name");
layout_type = intent.getStringExtra("layout_type");
watermark_image = intent.getStringExtra("watermark_image");
watermark_on_off = intent.getStringExtra("watermark_on_off");
assert watermark_on_off != null;
if (watermark_on_off.equals("true")) {
file_path = getExternalCacheDir().getAbsolutePath();
}
file_path_delete = file_path;
init();
}
if (intent.getAction() != null && intent.getAction().equals(ACTION_STOP)) {
stopForeground(true);
stopSelf();
if (gpuMp4Composer != null) {
gpuMp4Composer.cancel();
}
if (waterMarkData != null) {
waterMarkData.cancel(true);
}
if (!db.checkId_video_download(video_id)) {
db.delete_video_download(video_id);
}
File file = new File(file_path_delete, file_name);
if (file.exists()) {
file.delete();
}
Method.isDownload = true;
if (client != null) {
for (Call call : client.dispatcher().runningCalls()) {
if (call.request().tag().equals(CANCEL_TAG))
call.cancel();
}
}
}
return START_STICKY;
}
public void init() {
new Thread(new Runnable() {
#Override
public void run() {
client = new OkHttpClient();
Request.Builder builder = new Request.Builder()
.url(downloadUrl)
.addHeader("Accept-Encoding", "identity")
.get()
.tag(CANCEL_TAG);
Call call = client.newCall(builder.build());
call.enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
Log.e("TAG", "=============onFailure===============");
e.printStackTrace();
Log.d("error_downloading", e.toString());
Method.isDownload = true;
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
Log.e("TAG", "=============onResponse===============");
Log.e("TAG", "request headers:" + response.request().headers());
Log.e("TAG", "response headers:" + response.headers());
assert response.body() != null;
final ResponseBody responseBody = ProgressHelper.withProgress(response.body(), new ProgressUIListener() {
//if you don't need this method, don't override this methd. It isn't an abstract method, just an empty method.
#Override
public void onUIProgressStart(long totalBytes) {
super.onUIProgressStart(totalBytes);
Log.e("TAG", "onUIProgressStart:" + totalBytes);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.downloading), Toast.LENGTH_SHORT).show();
}
#Override
public void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed) {
Log.e("TAG", "=============start===============");
Log.e("TAG", "numBytes:" + numBytes);
Log.e("TAG", "totalBytes:" + totalBytes);
Log.e("TAG", "percent:" + percent);
Log.e("TAG", "speed:" + speed);
Log.e("TAG", "============= end ===============");
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = (int) (100 * percent) + "";
mHandler.sendMessage(msg);
}
//if you don't need this method, don't override this method. It isn't an abstract method, just an empty method.
#Override
public void onUIProgressFinish() {
super.onUIProgressFinish();
Log.e("TAG", "onUIProgressFinish:");
if (watermark_on_off.equals("true")) {
//call data watermark class add to watermark
waterMarkData = new WaterMarkData();
waterMarkData.execute();
} else {
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
showMedia(file_path, file_name);
}
}
});
try {
BufferedSource source = responseBody.source();
File outFile = new File(file_path + "/" + file_name);
BufferedSink sink = Okio.buffer(Okio.sink(outFile));
source.readAll(sink);
sink.flush();
source.close();
} catch (Exception e) {
Log.d("show_data", e.toString());
}
}
});
}
}).start();
}
#SuppressLint("StaticFieldLeak")
class WaterMarkData extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... strings) {
//check water mark on or off
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(downloadUrl);
mp.prepareAsync();
mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.d("call_data", "sizedata");
if (layout_type.equals("Portrait")) {
if (height <= 700) {
isResize = true;
}
} else {
if (height <= 400 || width <= 400) {
isResize = true;
}
}
watermark();//call method water mark adding
}
});
} catch (IllegalArgumentException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (SecurityException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (IllegalStateException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (IOException e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
} catch (Exception e) {
e.printStackTrace();
watermark();//call method water mark adding
Log.d("call_data", "error");
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d("data", "execute");
}
}
private void watermark() {
//check water mark on or off
new Thread(new Runnable() {
#Override
public void run() {
Bitmap image = null;
try {
URL url = new URL(watermark_image);
try {
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (Exception e) {
Log.d("error_data", e.toString());
}
} catch (IOException e) {
Log.d("error", e.toString());
System.out.println(e);
image = BitmapFactory.decodeResource(getResources(), R.drawable.watermark);
}
if (isResize) {
image = getResizedBitmap(image, 40, 40);
isResize = false;
}
String destinationPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Latest_Video_Status/";
file_path_delete = destinationPath;
gpuMp4Composer = new GPUMp4Composer(file_path + "/" + file_name, destinationPath + file_name)
.filter(new GlWatermarkFilter(image, GlWatermarkFilter.Position.RIGHT_BOTTOM))
.listener(new GPUMp4Composer.Listener() {
#Override
public void onProgress(double progress) {
isWaterMark = true;
double value = progress * 100;
int i = (int) value;
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = i + "";
mHandler.sendMessage(msg);
Log.d(TAG, "onProgress = " + progress);
Log.d("call_data", "watermark");
}
#Override
public void onCompleted() {
isWaterMark = false;
new File(getExternalCacheDir().getAbsolutePath() + "/" + file_name).delete();//delete file to save in cash folder
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
showMedia(destinationPath, file_name);
Log.d(TAG, "onCompleted()");
ServiceHandler sh = new ServiceHandler(this);
sh.run();
}
#Override
public void onCanceled() {
isWaterMark = false;
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
Log.d(TAG, "onCanceled");
}
#Override
public void onFailed(Exception exception) {
isWaterMark = false;
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
Method.isDownload = true;
Log.e(TAG, "onFailed()", exception);
}
})
.start();
}
}).start();
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
public void showMedia(String file_path, String file_name) {
try {
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{file_path + "/" + file_name},
null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}

E/AudioRecord: AudioFlinger could not create record track, status: -1

I had this error on my VoiSip Application
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioGroup: cannot initialize audio device
This error occurs after I'm trying to make call to another sip address
Here have 2 java class(WalkieTalkieActivity.java & IncomingCallReceiver.java)
WalkieTalkieActivity.java
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public IncomingCallReceiver callReceiver;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public SipAudioCall call = null;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
if (mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
tv = (TextView)findViewById(R.id.textView);
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
public void initializeManager() {
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
String domain = "mydomain";
String username = "myusername";
String password = "mypassword";
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
if (mSipProfile == null){
Log.e("error cukimai", "null");
}else{
Log.e("error cukimai", "not null");
}
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pi, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
Log.e("process","Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
Log.e("process","ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
Log.e("process","Registration failed. Please check settings.");
}
});
Log.e("process","stop");
} catch (SipException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk cuk");
} catch (ParseException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk");
}
}
public void updateStatus(final String st){
this.runOnUiThread(new Runnable() {
public void run() {
tv.setText(st);
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public void callAct(View view) {
Toast.makeText(this, "about to make call", Toast.LENGTH_LONG).show();
makeCall();
}
public void makeCall(){
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), "sip:destination#domain", listener, 30);
Log.e("make call", "true");
start();
}catch (Exception e){
Log.i("error", "Error when trying to close manager.", e);
if (mSipProfile != null) {
try {
mSipManager.close(mSipProfile.getUriString());
} catch (Exception ee) {
Log.i("error", "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public WalkieTalkieActivity(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
IncomingCallReceiver.java
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
I'm really new on Sip and Voip Implementing in Android Studio. I got this code from google source code.
I believe this error occurs because of the use of hardware (audio). However I have been searching on google for almost 1 week and not giving results. Can someone help me?
I had same problem but when i changed targetSdkVersion to 12 in build.gradel its fixed.
and this answer helped me to fixed problem .
You must choose the BufferSize when you want to record or call in app. For example:
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize > 0 && bufferSize <= 256){
bufferSize = 256;
}else if (bufferSize > 256 && bufferSize <= 512){
bufferSize = 512;
}else if (bufferSize > 512 && bufferSize <= 1024){
bufferSize = 1024;
}else if (bufferSize > 1024 && bufferSize <= 2048){
bufferSize = 2048;
}else if (bufferSize > 2048 && bufferSize <= 4096){
bufferSize = 4096;
}else if (bufferSize > 4096 && bufferSize <= 8192){
bufferSize = 8192;
}else if (bufferSize > 8192 && bufferSize <= 16384){
bufferSize = 16384;
}else{
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
}

Android call recorder application

I have developed basic call recorder application, its working fine on devices with versions below 'lollipop', but when I have to run lollipop devices (Android 5.0) I'm getting this error.
E/MediaRecorder(29786): start failed: -2147483648
java.lang.RuntimeException: start failed.
at android.media.MediaRecorder.start(Native Method)
at com.androiddoc.callRecorder_anirbanjana.CallRecordingService.startRec(CallRecordingService.java:234)
at com.androiddoc.callRecorder_anirbanjana.CallRecordingService.onCreate(CallRecordingService.java:54)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2763)
at android.app.ActivityThread.access$1800(ActivityThread.java:148)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1375)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
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:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
My code is below. When I call recorder.prepare(); and recorder.start(); Now I'm getting above error and I can't work out why. Can anyone advise?
public class CallRecordingService extends Service {
MediaRecorder myRec = new MediaRecorder();
boolean isRecMode = false;
private static final int RECORDER_SAMPLERATE = 8000;
private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_MONO;
private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private AudioRecord recorder = null;
private Thread recordingThread = null;
private boolean isRecording = false;
int bufferSize = AudioRecord.getMinBufferSize(RECORDER_SAMPLERATE,
RECORDER_CHANNELS, RECORDER_AUDIO_ENCODING);
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY_COMPATIBILITY;
}
#Override
public void onCreate() {
// Start recording
startRec();
System.out.println("BUFFER SIZE VALUE IS " + bufferSize);
super.onCreate();
}
public void stopRec() {
myRec.reset();
Toast.makeText(CallRecordingService.this, "Rec Stoped",
Toast.LENGTH_SHORT).show();
Log.i("CallRecordingService", "Rec Stoped");
isRecMode = false;
}
public void startRec() {
try {
// String selectedPath = this.getApplicationContext().getFilesDir()
// + "/system_sound";
String selectedPath = Environment.getExternalStorageDirectory()
+ "/Testing";
SimpleDateFormat sdf = new SimpleDateFormat(
"dd_MM_yyyy_hh_mm_ss aa");
String currentDateandTime = sdf.format(new Date());
// Crate folder if not exist
// String packageName = this.getPackageName();
File yourDir = new File(Environment.getExternalStorageDirectory()
+ "/Testing");
// File yourDir = new
// File(this.getApplicationContext().getFilesDir() +
// "/system_sound");
if (!yourDir.exists()) {
yourDir.mkdirs();
}
// String selectedPath =
// Environment.getExternalStorageDirectory().getAbsolutePath() +
// "/Android/data/" + packageName + "/system_sound";
myRec.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
myRec.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
myRec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
// myRec.setOutputFile(Environment.getExternalStorageDirectory().getPath()+"/my_rec_voice.mp3");
myRec.setOutputFile(selectedPath + "/" + currentDateandTime + "_"
+ getFromPreference("phoneNo") + ".amr");
AudioManager am; // Audio manager
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.setMode(AudioManager.MODE_IN_CALL);
int volume_level = am
.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
int max_volume = am
.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
if (volume_level < max_volume) {
am.setStreamVolume(AudioManager.STREAM_VOICE_CALL, max_volume,
AudioManager.FLAG_SHOW_UI);
}
} catch (IllegalStateException e) {
// Log.e("Call recorder IllegalStateException: ", "");
terminateAndEraseFile();
} catch (Exception e) {
// Log.e("Call recorder Exception: ", "");
terminateAndEraseFile();
}
OnErrorListener errorListener = new OnErrorListener() {
public void onError(MediaRecorder arg0, int arg1, int arg2) {
terminateAndEraseFile();
}
};
myRec.setOnErrorListener(errorListener);
try {
Log.v("Call Recorder", "Media recorder prepared");
myRec.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Log.v("Call Recorder", "Media recorder started ");
myRec.start();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(CallRecordingService.this, "Rec Start",
Toast.LENGTH_SHORT).show();
Log.i("CallRecordingService", "Rec Start");
isRecMode = true;
}
#Override
public void onDestroy() {
stopRec();
//stopRecording();
if (isRecMode) {
// Stop recording
myRec.stop();
}
myRec.release();
super.onDestroy();
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Preference Variable
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// --------------------------------------------
// method to save variable in preference
// --------------------------------------------
public void saveInPreference(String name, String content) {
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(name, content);
editor.commit();
}
// --------------------------------------------
// getting content from preferences
// --------------------------------------------
public String getFromPreference(String variable_name) {
String preference_return;
SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(this);
preference_return = preferences.getString(variable_name, "");
return preference_return;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Preference Variable
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
private void terminateAndEraseFile() {
try {
Toast toast = Toast.makeText(this,
this.getString(R.string.reciever_end_call),
Toast.LENGTH_SHORT);
toast.show();
} catch (IllegalStateException e) {
e.printStackTrace();
}
Toast toast = Toast.makeText(this,
this.getString(R.string.record_impossible), Toast.LENGTH_LONG);
toast.show();
}
}
If you get start failed for VOICE_CALL then use MIC.
VOICE_CALL is allowed only for system apps.
Here is the detailed code:
int audioSource = MediaRecorder.AudioSource.MIC;
mediaRecorder.setAudioSource(audioSource);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioEncodingBitRate(32);
mediaRecorder.setAudioSamplingRate(44100);
mediaRecorder.setOutputFile(MediaUri);
mediaRecorder.prepare();
mediaRecorder.start();

while updating(editing) its not taking the old audio file name

having one text and audio(recording) and saving the name and path in db.while clicking the name that audio has to play its playing also.But while editing if i supposed to change the name alone,it will not take the old file name of the respective one,its make that one as null.
How to take the old audio file name if people will not update the audio(recording)
audioactivity.java
private void saveState() {
String audioname = et1.getText().toString();
String audiofilename = gfilename;
String audiocount = et2.getText().toString();
if(audiocount.equals("")){
audiocount ="1";
}
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
String audiodate = sdf.format(new Date());
if (mRowId == null || mRowId.longValue() == 0)
{
long id = mDbHelper.createProject4(audioname, audiofilename, audiocount, audiodate);
if (id > 0) {
mRowId = id;
}
} else {
audiofilename=gfilename;
mDbHelper.updateProject4(mRowId, audioname, audiofilename, audiocount,audiodate);
}
}
public View.OnClickListener btnClick = new View.OnClickListener()
{
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btnStart:{
AppLog.logString("Start Recording");
enableButtons(true);
startRecording();
break;
}
case R.id.btnstop:{
AppLog.logString("Start Recording");
enableButtons(false);
stopRecording();
break;
}
}
}
};
public MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
AppLog.logString("Error: " + what + ", " + extra);
}
};
public MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
AppLog.logString("Warning: " + what + ", " + extra);
}
};
public void setButtonHandlers() {
((Button)findViewById(R.id.btnStart)).setOnClickListener(btnClick);
((Button)findViewById(R.id.btnstop)).setOnClickListener(btnClick);
}
public void enableButton(int id,boolean isEnable){
((Button)findViewById(id)).setEnabled(isEnable);
}
public void enableButtons(boolean isRecording) {
enableButton(R.id.btnStart,!isRecording);
enableButton(R.id.btnstop,isRecording);
}
#SuppressLint("NewApi")
private void startRecording(){
//displayFormatDialog();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
String formats[] = {"MPEG 4", "3GPP", "AMR"};
builder.setTitle(getString(R.string.choose_format_title))
.setSingleChoiceItems(formats, currentFormat, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
currentFormat = which;
dialog.dismiss();
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(output_formats[currentFormat]);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(getFilename());
//recorder.setOnErrorListener(errorListener);
//recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
})
.show();
}
private void stopRecording(){
if(null != recorder)
{
//mDbHelper.updateProject4FileName(mRowId, gfilename);
recorder.stop();
recorder.reset();
recorder.release();
recorder = null;
}
else
{
recorder.stop();
recorder.release();
}
}
public String getFilename(){
String filepath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filepath,AUDIO_RECORDER_FOLDER);
if(!file.exists()){
file.mkdirs();
}
gfilename = (file.getAbsolutePath() + "/" + System.currentTimeMillis() + file_exts[currentFormat]);
return (gfilename);
}
#Override
public void onCompletion (MediaPlayer arg0)
{
}
public void playSong(String gfilename){
// Play song
try
{
mp.reset();
mp.setDataSource(gfilename);
mp.prepare();
mp.start();
// Changing Button Image to pause image
btnPlay.setImageResource(R.drawable.btn_pause);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
I checked in debugging also,if we didnt update the recording its taking that place as null only.
Here i attached my db updated code also
public boolean updateProject4(long _id, String audioname, String audiofilename,String audiocount,String audiodate) {
ContentValues args = new ContentValues();
args.put(CATEGORY_COLUMN_AUDIONAME, audioname );
args.put(CATEGORY_COLUMN_AUDIOFILENAME, audiofilename );
args.put(CATEGORY_COLUMN_AUDIOCOUNT, audiocount );
args.put(CATEGORY_COLUMN_AUDIODATE, audiodate );
return mDb.update(DATABASE_TABLE_AUDIOPRAYER, args, CATEGORY_COLUMN_ID4 + "=" + _id, null) > 0;
}
Actually i got the way for my question.
Want to fetchfile from db if my filename becomes null while updating
private void saveState() {
String audioname = et1.getText().toString();
String audiofilename = gfilename;
String audiocount = et2.getText().toString();
if(audiocount.equals("")){
audiocount ="1";
}
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
String audiodate = sdf.format(new Date());
//String reqname= spin.getSelectedItem().toString();
//Log.i(" save state mathod "," values are "+title+Desc+Body+reqname);
if (mRowId == null || mRowId.longValue() == 0)
{
long id = mDbHelper.createProject4(audioname, audiofilename, audiocount, audiodate);
if (id > 0) {
mRowId = id;
}
} else {
if(audiofilename.equals("")){
Cursor filename = mDbHelper.fetchProject4FileName(mRowId, audiofilename);
startManagingCursor(filename);
gfilename =filename.getString(filename.getColumnIndexOrThrow(GinfyDbAdapter.CATEGORY_COLUMN_AUDIOFILENAME));
//mDbHelper.fetchProject4FileName(mRowId, audiofilename);
audiofilename = gfilename;
mDbHelper.updateProject4(mRowId, audioname, audiofilename, audiocount,audiodate);
}
else
{
audiofilename = gfilename;
mDbHelper.updateProject4(mRowId, audioname, audiofilename, audiocount,audiodate);
}
}
we have to fetch the filename from db and check whether our audiofilename is null means,we have to set the older filename

Categories

Resources