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());
}
}
}
}
Related
This is code of image and video of instagram dowloading by link.. after downloading 4 ,5 photos or videos this code not work .and getting error findata class ..
public class FindData {
private Context context;
private GetDat getData;
String netsubType;
NetworkInfo activeNetworkInfo1;
Boolean s;
public FindData(Context context, GetDat getData) {
this.context = context;
this.getData = getData;
}
public void data(String stringData) {
ArrayList<String> arrayList = new ArrayList<>();
if (stringData.matches("https://www.instagram.com/(.*)")) {
String[] data = stringData.split(Pattern.quote("?"));
String string = data[0];
// if (isNetworklow()) {
//
// Toast.makeText(context, "network low", Toast.LENGTH_SHORT).show();
// }
if (isNetworkAvailable()) {
if (Method.isDownload) {
AsyncHttpClient client = new AsyncHttpClient();
client.get(string + "?__a=1", null, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
String res = new String(responseBody);
try {
JSONObject jsonObject = new JSONObject(res);
String link = null;
JSONObject objectGraphql = jsonObject.getJSONObject("graphql");
JSONObject objectMedia = objectGraphql.getJSONObject("shortcode_media");
boolean isVideo = objectMedia.getBoolean("is_video");
if (isVideo) {
link = objectMedia.getString("video_url");
} else {
link = objectMedia.getString("display_url");
}
arrayList.add(link);
try {
JSONObject objectSidecar = objectMedia.getJSONObject("edge_sidecar_to_children");
JSONArray jsonArray = objectSidecar.getJSONArray("edges");
arrayList.clear();
String edgeSidecar = null;
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
JSONObject node = object.getJSONObject("node");
boolean is_video_group = node.getBoolean("is_video");
if (is_video_group) {
edgeSidecar = node.getString("video_url");
} else {
edgeSidecar = node.getString("display_url");
}
arrayList.add(edgeSidecar);
}
} catch (Exception e) {
Log.e("error_show", e.toString());
}
getData.getData(arrayList, "", true);
Toast.makeText(context, "success", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
Log.e("........POOR NETWORK ........", e.toString());
getData.getData(arrayList, context.getResources().getString(R.string.not_support), false);
Toast.makeText(context, " poor network", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.e("...........on failure +Tag............",error.toString());
Toast.makeText(context, "try again error", Toast.LENGTH_SHORT).show();
getData.getData(arrayList, context.getResources().getString(R.string.wrong), false);
}
});
} else {
getData.getData(arrayList,"ff ", false);
}
} else {
getData.getData(arrayList, context.getResources().getString(R.string.internet_connection), false);
Toast.makeText(context, "no network", Toast.LENGTH_SHORT).show();
}
} else {
getData.getData(arrayList, "invalid link copy again", false);
}
}
//network check
public boolean isNetworkAvailable() {
Log.e("TAG", "=============onFailure===============");
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
//netsubType.equals( TelephonyManager.NETWORK_TYPE_EDGE)||netsubType.equals( TelephonyManager.NETWORK_TYPE_1xRTT ));
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
}
public class DownloadService extends Service {
private int position = 0;
private RemoteViews rv;
private OkHttpClient client;
private final int CHANEL_ID = 105;
private NotificationCompat.Builder builder;
private NotificationManager notificationManager;
private static final String CANCEL_TAG = "c_tag";
private final String NOTIFICATION_CHANNEL_ID = "download_service";
public static final String ACTION_START = "com.download.action.START";
public static final String ACTION_STOP = "com.download.action.STOP";
private final Handler mHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(#NotNull 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);
rv.setTextViewText(R.id.nf_percentage, getResources().getString(R.string.downloading) + " " + "(" + progress + " %)");
notificationManager.notify(CHANEL_ID, builder.build());
break;
case 2:
if (Constant.downloadArray.size() - 1 != position) {
position++;
init(Constant.downloadArray.get(position));
} else {
// Toast.makeText(getApplicationContext(), getResources().getString(R.string.downloading), Toast.LENGTH_SHORT).show();
position = 0;
stopForeground(false);
stopSelf();
Events.AdapterNotify adapterNotify = new Events.AdapterNotify("");
GlobalBus.getBus().post(adapterNotify);
Method.isDownload = true;
}
break;
}
return false;
}
});
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_baseline_notes);
builder.setTicker(getResources().getString(R.string.downloading));
builder.setWhen(System.currentTimeMillis());
builder.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 intentClose = new Intent(this, DownloadService.class);
intentClose.setAction(ACTION_STOP);
PendingIntent closeIntent = PendingIntent.getService(this, 0, intentClose, 0);
rv.setOnClickPendingIntent(R.id.nf_close, closeIntent);
builder.setCustomContentView(rv);
NotificationChannel mChannel;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getResources().getString(R.string.app_name);// The user-visible name of the channel.
mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(mChannel);
}
startForeground(CHANEL_ID, builder.build());
}
#Override
public void onDestroy() {
super.onDestroy();
stopForeground(false);
stopSelf();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
try {
if (intent.getAction() != null && intent.getAction().equals(ACTION_START)) {
Method.isDownload = false;
init(Constant.downloadArray.get(position));
}
if (intent.getAction() != null && intent.getAction().equals(ACTION_STOP)) {
if (client != null) {
for (Call call : client.dispatcher().runningCalls()) {
if (call.request().tag().equals(CANCEL_TAG))
call.cancel();
}
}
Method.isDownload = true;
stopForeground(false);
stopSelf();
}
} catch (Exception e) {
Log.d("error", e.toString());
stopForeground(false);
stopSelf();
}
return START_STICKY;
}
public void init(final String downloadUrl) {
final String iconsStoragePath = Environment.getExternalStorageDirectory() + getResources().getString(R.string.download_folder_path);
File file = new File(iconsStoragePath);
if (!file.exists()) {
file.mkdir();
}
//Using Date class
Date date = new Date();
//Pattern for showing milliseconds in the time "SSS"
#SuppressLint("SimpleDateFormat")
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
String stringDate = sdf.format(date);
//Using Calendar class
Calendar cal = Calendar.getInstance();
String s = sdf.format(cal.getTime());
final String string;
if (downloadUrl.contains(".jpg")) {
string = "Image-" + s + ".jpg";
} else {
string = "Image-" + s + ".mp4";
}
Log.d("file_name", string);
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", "=============onFailure222===============");
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;
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);
}
#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 methd. It isn't an abstract method, just an empty method.
#Override
public void onUIProgressFinish() {
super.onUIProgressFinish();
Log.e("TAG", "onUIProgressFinish:");
Message msg = mHandler.obtainMessage();
msg.what = 2;
msg.obj = 0 + "";
mHandler.sendMessage(msg);
if (downloadUrl.contains(".jpg")) {
if (Constant.imageArray != null) {
Constant.imageArray.add(0, new File(iconsStoragePath + "/" + string));
}
} else {
if (Constant.videoArray != null) {
Constant.videoArray.add(0, new File(iconsStoragePath + "/" + string));
}
}
try {
MediaScannerConnection.scanFile(getApplicationContext(), new String[]{iconsStoragePath + "/" + string},
null,
(path, uri) -> {
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
try {
BufferedSource source = responseBody.source();
File outFile = new File(iconsStoragePath + "/" + string);
BufferedSink sink = Okio.buffer(Okio.sink(outFile));
source.readAll(sink);
sink.flush();
source.close();
} catch (Exception e) {
Log.d("show_data", e.toString());
}
}
});
}
}).start();
}
}
**error in FindData class2022-03-11 08:32:20.701 1631-1631/?
E/downloaderinst: Unknown bits set in runtime_flags: 0x8000
2022-03-11 08:59:02.413 1631-1631/com.pinit.downloaderinst3 E/TAG: =============onFailure===============
2022-03-11 08:59:02.539 1631-1631/com.pinit.downloaderinst3 E/DecorView: mWindow.mActivityCurrentConfig is null
2022-03-11 08:59:03.999 1631-1631/com.pinit.downloaderinst3 E/........POOR NETWORK ........: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject
2022-03-11 08:59:04.007 1631-1631/com.pinit.downloaderinst3 E/InputMethodManager: prepareNavigationBarInfo() rootView is null
2022-03-11 08:59:04.123 1631-1631/com.pinit.downloaderinst3 E/ViewRootImpl: sendUserActionEvent() mView returned.
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();
}
}
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;
}
}
Still with the same project, this is a continuation from Run pocketSphinx and Google TTS together. I already do the revision according to the guide from Nikolay Shymyrev and do a lot of helping. But the final feature that I want implement still remains. The Google TTS run just fine now, but the recognizer have some problem.
the recognizer won't start if the Google TTS some words that quite long like
Speaker.speak("Drive mode now will be enabled. I will read your new messages for you now.");
and then my onPartialResult if condition cannot fulfilled like
if (text.equals("exit")) {
speaker.speak("yeah get in");
recognizer.cancel();
Intent i = new Intent(getApplicationContext(),PocketSphinxActivity.class);
startActivity(i);
I think the recognizer always listen since it runs in background, and then it listen the google TTS sentence that caused it won't recognize my speech afterwards. Because when I use handsfree with mic, and the sentence for speaker.Speak is just "Drive mode enabled", it recognize well my word next and execute the if condition above when I say "exit". But when the sentence is quite long like "Drive mode now will be enabled, I will read bla bla bla" it won't listen to my "exit" word.
What I want to do now is add timeout to the recognizer to timeout several momment so that it wont recognize any unnecessary sound. I want to put
startRecognition("search", timeout)
but my Eclipse won't me let do that. It gives me error. I'm Using PocketSphinx for Android 5 pre alpha.
Here's again, my code that build just to test and make sure it recognize just "exit" words
SMSReaderMain.java
public class SMSReaderMain extends Activity implements RecognitionListener {
private final int CHECK_CODE = 0x1;
private final int LONG_DURATION = 5000;
private final int SHORT_DURATION = 1200;
private Speaker speaker;
private TextView smsText;
private TextView smsSender;
private BroadcastReceiver smsReceiver;
public static final String TURNON_SR = "drive mode";
public static final String TURNOFF_SR = "ok";
public static final String DESTROY_SR = "exit";
public SpeechRecognizer recognizer;
public HashMap<String, Integer> captions;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_sms);
captions = new HashMap<String, Integer>();
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(SMSReaderMain.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) findViewById(R.id.caption_text))
.setText("Failed to init recognizer " + result);
} else {
switchSearch(TURNOFF_SR);
}
}
}.execute();
//toggle = (ToggleButton)findViewById(R.id.speechToggle);
smsText = (TextView)findViewById(R.id.sms_text);
smsSender = (TextView)findViewById(R.id.sms_sender);
checkTTS();
}
private void startDriveMode(){
speaker.allow(true);
//speaker.speak(getString(R.string.start_speaking));
speaker.speak("Drive mode enabled");
}
private void checkTTS(){
Intent check = new Intent();
check.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(check, CHECK_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == CHECK_CODE){
if(resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS)
{
speaker = new Speaker(this);
}else {
Intent install = new Intent();
install.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(install);
}
}
startDriveMode();
initializeSMSReceiver();
registerSMSReceiver();
}
private void initializeSMSReceiver(){
smsReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle!=null){
Object[] pdus = (Object[])bundle.get("pdus");
for(int i=0;i<pdus.length;i++){
byte[] pdu = (byte[])pdus[i];
SmsMessage message = SmsMessage.createFromPdu(pdu);
String text = message.getDisplayMessageBody();
String sender = getContactName(message.getOriginatingAddress());
speaker.pause(LONG_DURATION);
speaker.speak("You have a new message from" + sender + "!");
speaker.pause(SHORT_DURATION);
speaker.speak(text);
smsSender.setText("Message from " + sender);
smsText.setText(text);
}
}
}
};
}
private void registerSMSReceiver() {
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(smsReceiver, intentFilter);
}
private String getContactName(String phone){
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
String projection[] = new String[]{ContactsContract.Data.DISPLAY_NAME};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if(cursor.moveToFirst()){
return cursor.getString(0);
}else {
return "unknown number";
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(smsReceiver);
speaker.destroy();
}
public void onPartialResult(Hypothesis hypothesis) {
//System.out.println("masuk coiii");
String text = hypothesis.getHypstr();
try {
if (text.equals("exit")) {
speaker.speak("yeah get in");
recognizer.cancel();
Intent i = new Intent(getApplicationContext(),PocketSphinxActivity.class);
startActivity(i);
}
//Intent i= null;
/**if (text.equals(TURNON_SR)) {
recognizer.cancel();
popPicture();
startDriveMode();
}
if (text.equals(TURNOFF_SR)) {
//speaker = new Speaker(this);
speaker.speak(getString(R.string.stop_speaking));
speaker.allow(false);
//popPicture2();
}
if (text.equals(DESTROY_SR)) {
recognizer.cancel();
i = new Intent(getApplicationContext(),PocketSphinxActivity.class);
startActivity(i);
onDestroy();
//popPicture2();
} **/
} catch (Exception e) {
e.printStackTrace();
}
}
public void popPicture() {
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_image,(ViewGroup)
findViewById(R.id.toast_layout_id));
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_HORIZONTAL, 0, 0);
toast.setDuration(Toast.LENGTH_SHORT);
toast.setView(layout);
toast.show();
}
public void onResult(Hypothesis hypothesis) {
((TextView) findViewById(R.id.result_text)).setText("");
if (hypothesis != null) {
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
}
public void switchSearch(String searchName) {
recognizer.stop();
recognizer.startListening(searchName);
//taro timout disini biar mic ga denger suara hp sendiri
((TextView) findViewById(R.id.caption_text)).setText(searchName);
}
public void setupRecognizer(File assetsDir) {
File modelsDir = new File(assetsDir, "models");
recognizer = defaultSetup()
.setAcousticModel(new File(modelsDir, "hmm/en-us-semi"))
.setDictionary(new File(modelsDir, "dict/cmu07a.dic"))
.setRawLogDir(assetsDir).setKeywordThreshold(1e-10f)
.getRecognizer();
recognizer.addListener(this);
// Create grammar-based searches.
// recognizer.addKeyphraseSearch(TURNOFF_SR, TURNON_SR);
//recognizer.addGrammarSearch(TURNON_SR, new File(modelsDir, "grammar/sms.gram"));
//recognizer.addGrammarSearch(TURNOFF_SR, new File(modelsDir, "grammar/sms.gram"));
//recognizer.addGrammarSearch(DESTROY_SR, new File(modelsDir, "grammar/sms.gram"));
File menuGrammar = new File(modelsDir, "grammar/sms.gram");
recognizer.addGrammarSearch(TURNOFF_SR, menuGrammar);
//recognizer.addGrammarSearch(TURNON_SR, menuGrammar);
//recognizer.addGrammarSearch(DESTROY_SR, menuGrammar);
}
#Override
public void onBeginningOfSpeech() {
// TODO Auto-generated method stub
}
#Override
public void onEndOfSpeech() {
// TODO Auto-generated method stub
}
}
Speaker.java
public class Speaker implements OnInitListener {
private TextToSpeech tts;
private boolean ready = false;
private boolean prematureSpeak = false;
private String ps;
private boolean allowed = false;
public Speaker(Context context){
tts = new TextToSpeech(context, this);
}
public boolean isAllowed(){
return allowed;
}
//public void allow(boolean allowed){
public void allow(boolean allowed){
this.allowed = allowed;
}
#Override
public void onInit(int status) {
if(status == TextToSpeech.SUCCESS){
// Change this to match your
// locale
tts.setLanguage(Locale.US);
ready = true;
if (prematureSpeak)
{
speak(ps);
prematureSpeak = false;
}
}else{
ready = false;
}
}
public void speak(String text){
// Speak only if the TTS is ready
// and the user has allowed speech
if(ready && allowed) {
HashMap<String, String> hash = new HashMap<String,String>();
hash.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
String.valueOf(AudioManager.STREAM_NOTIFICATION));
tts.speak(text, TextToSpeech.QUEUE_ADD, hash);
}
else if(!ready) {
prematureSpeak = true;
ps = text;
}
}
public void pause(int duration){
tts.playSilence(duration, TextToSpeech.QUEUE_ADD, null);
}
// Free up resources
public void destroy(){
tts.shutdown();
}
public boolean isSpeaking()
{
return tts.isSpeaking();
}
}
Your code has several issues:
1) I told you to use keyword spotting mode, you are still using grammar mode
2) You need to cancel recognizer before you start voice feedback, instead of first speak then cancel
if (text.equals("exit")) {
speaker.speak("yeah get in");
recognizer.cancel();
....
you need to first cancel then speak:
if (text.equals("exit")) {
recognizer.cancel();
speaker.speak("yeah get in");
....
3) Once speaker is over you need to restart the recognizer, but there is no need to run activity again, see for details How to know when TTS is finished?
With those changes in onUtteranceEnded you start recognizer again:
public void onUtteranceCompleted(String utteranceId) {
recognizer.startSearch("search name");
}
Do not restart recognizer in onPartialResult, wait till TTS will finish.
In my application some data is there which is wrapped into an object.
I am sending this object to the server. Everything work correctly.
Here I want to show progress bar when the data is loading to the server.
For this I am using this code:
ProgressThread progThread;
ProgressDialog progDialog;
int typeBar;
int delay = 40;
int maxBarValue = 200;
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case 1:
progDialog = new ProgressDialog(this);
progDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progDialog.setMax(maxBarValue);
progDialog.setMessage("Data uploading to the Server..");
progThread = new ProgressThread(handler);
progThread.start();
return progDialog;
default:
return null;
}
}
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
// Get the current value of the variable total from the message data
// and update the progress bar.
int total = msg.getData().getInt("total");
progDialog.setProgress(total);
if (total <= 0) {
dismissDialog(typeBar);
progThread.setState(ProgressThread.DONE);
}
}
};
private class ProgressThread extends Thread {
final static int DONE = 0;
final static int RUNNING = 1;
Handler mHandler;
int mState;
int total;
ProgressThread(Handler h) {
mHandler = h;
}
#Override
public void run() {
mState = RUNNING;
total = maxBarValue;
while (mState == RUNNING) {
connectServerClass.saveOnServer(Object);
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putInt("total", total);
msg.setData(b);
mHandler.sendMessage(msg);
total--; // Count down
}
}
public void setState(int state) {
mState = state;
}
}
When user click on button then:
typeBar = 1;
showDialog(typeBar);
connectServerClass.saveOnServer(Object)
by the above line I am sending object to the server. Actually I am sending data to the other class which is connectServerClass and this class send object to the server.
but this code not work correctly. This code connect to the server lots of time.
I use the following Code :
private class Uploader extends AsyncTask<Void, String, Integer>
{
private List<File> files;
private boolean canceled;
private int uploaded;
private Account account;
private ProgressDialog uploadSeekBar;
public Uploader(Account a, List<File> files)
{
this.account = a;
this.files = files;
}
#Override
protected void onPreExecute()
{
uploadSeekBar.setMax(files.size());
uploadSeekBar.setProgress(0);
uploadSeekBar.setVisibility(View.VISIBLE); //Error: the method setVisibility is undefined
}
#Override
protected void onPostExecute(Integer result)
{
uploadSeekBar.setVisibility(View.INVISIBLE);
Toast.makeText(Upload.this, result + " files uploaded", // Error: Upload cannot be resolved to a type
Toast.LENGTH_LONG).show();
}
#Override
protected void onCancelled()
{
// XXX need a way to actually cancel the last upload
Toast.makeText(Upload.this, "canceling upload", Toast.LENGTH_LONG)
.show();
this.canceled = true;
uploadSeekBar.setVisibility(View.INVISIBLE);
}
#Override
protected Integer doInBackground(Void... voids)
{
uploaded = 0;
try
{
Iterator<File> it = this.files.iterator();
while (!canceled && it.hasNext())
{
File file = it.next();
it.remove();
String msg = "";
try
{
if (debugMode) // what is this debugMode
{
//Put your uploading code here.
msg = ("fake uploading " + file);
Thread.sleep(3000);
} else
{
msg = ("uploading: " + file);
controller.uploadFile(file, this.account); //Error: controller cannot be resolved
}
uploaded++;
publishProgress(msg);
} catch (IOException e)
{
controller.te("error uploading file: " + file);
controller.te("error uploading file: " + e);
} catch (InterruptedException e)
{
}
}
} catch (Exception e)
{
publishProgress("error uploading: " + e);
}
return uploaded;
}
#Override
protected void onProgressUpdate(String... strings)
{
uploadSeekBar.setProgress(uploaded);
updateUploadMessage(files.size());
Toast.makeText(Upload.this, strings[0], Toast.LENGTH_LONG).show(); //Error: The method updateUploadMessage(int) is undefined for the type FirstActivity.Uploader
}
}
But I facing some error which I mention as comment in the right side of that line. Please suggest me.
I will strongly recommend you to Use AsyncTask.
Below Code snippet will help you on How your AsyncTask should look like.
package org.sample;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import android.accounts.Account;
import android.os.AsyncTask;
import android.view.View;
import android.widget.Toast;
private class Uploader extends AsyncTask<Void, String, Integer>
{
private List<File> files;
private boolean canceled;
private int uploaded;
public Uploader(Account a, List<File> files)
{
this.account = a;
this.files = files;
}
#Override
protected void onPreExecute()
{
uploadSeekBar.setMax(files.size());
uploadSeekBar.setProgress(0);
uploadSeekBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(Integer result)
{
uploadSeekBar.setVisibility(View.INVISIBLE);
Toast.makeText(Upload.this, result + " files uploaded",
Toast.LENGTH_LONG).show();
}
#Override
protected void onCancelled()
{
// XXX need a way to actually cancel the last upload
Toast.makeText(Upload.this, "canceling upload", Toast.LENGTH_LONG)
.show();
this.canceled = true;
uploadSeekBar.setVisibility(View.INVISIBLE);
}
#Override
protected Integer doInBackground(Void... voids)
{
uploaded = 0;
try
{
Iterator<File> it = this.files.iterator();
while (!canceled && it.hasNext())
{
File file = it.next();
it.remove();
String msg = "";
try
{
if (debugMode)
{
//Put your uploading code here.
msg = ("fake uploading " + file);
Thread.sleep(3000);
} else
{
msg = ("uploading: " + file);
controller.uploadFile(file, this.account);
}
uploaded++;
publishProgress(msg);
} catch (IOException e)
{
controller.te("error uploading file: " + file);
controller.te("error uploading file: " + e);
} catch (InterruptedException e)
{
}
}
} catch (Exception e)
{
publishProgress("error uploading: " + e);
}
return uploaded;
}
#Override
protected void onProgressUpdate(String... strings)
{
uploadSeekBar.setProgress(uploaded);
updateUploadMessage(files.size());
Toast.makeText(Upload.this, strings[0], Toast.LENGTH_LONG).show();
}
}