@ -79,6 +79,11 @@ import androidx.core.content.ContextCompat;
import androidx.annotation.NonNull ;
import androidx.annotation.Nullable ;
import com.baidu.speech.EventListener ;
import com.baidu.speech.EventManager ;
import com.baidu.speech.EventManagerFactory ;
import com.baidu.speech.asr.SpeechConstant ;
import net.micode.notes.R ;
import net.micode.notes.data.Notes ;
import net.micode.notes.data.Notes.TextNote ;
@ -92,20 +97,24 @@ import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x ;
import net.micode.notes.widget.NoteWidgetProvider_4x ;
import org.json.JSONException ;
import org.json.JSONObject ;
import java.io.FileNotFoundException ;
import java.text.BreakIterator ;
import java.util.Locale ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.HashSet ;
import java.util.L ocale ;
import java.util.L inkedHashMap ;
import java.util.Map ;
import java.util.regex.Matcher ;
import java.util.regex.Pattern ;
public class NoteEditActivity extends Activity implements OnClickListener ,
NoteSettingChangedListener , OnTextViewChangeListener {
NoteSettingChangedListener , OnTextViewChangeListener , EventListener {
private AlertDialog alertDialog2 ;
private class HeadViewHolder {
public TextView tvModified ;
@ -119,6 +128,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map < Integer , Integer > sBgSelectorBtnsMap = new HashMap < Integer , Integer > ( ) ;
static {
sBgSelectorBtnsMap . put ( R . id . iv_bg_yellow , ResourceParser . YELLOW ) ;
sBgSelectorBtnsMap . put ( R . id . iv_bg_red , ResourceParser . RED ) ;
@ -128,6 +138,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map < Integer , Integer > sBgSelectorSelectionMap = new HashMap < Integer , Integer > ( ) ;
static {
sBgSelectorSelectionMap . put ( ResourceParser . YELLOW , R . id . iv_bg_yellow_select ) ;
sBgSelectorSelectionMap . put ( ResourceParser . RED , R . id . iv_bg_red_select ) ;
@ -137,6 +148,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map < Integer , Integer > sFontSizeBtnsMap = new HashMap < Integer , Integer > ( ) ;
static {
sFontSizeBtnsMap . put ( R . id . ll_font_large , ResourceParser . TEXT_LARGE ) ;
sFontSizeBtnsMap . put ( R . id . ll_font_small , ResourceParser . TEXT_SMALL ) ;
@ -145,6 +157,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final Map < Integer , Integer > sFontSelectorSelectionMap = new HashMap < Integer , Integer > ( ) ;
static {
sFontSelectorSelectionMap . put ( ResourceParser . TEXT_LARGE , R . id . iv_large_select ) ;
sFontSelectorSelectionMap . put ( ResourceParser . TEXT_SMALL , R . id . iv_small_select ) ;
@ -189,6 +202,11 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private EditText editText ;
private TextView textView ;
protected EditText txtResult ; //识别结果
protected Button startBtn ; //开始识别 一直不说话会自动停止,需要再次打开
private EventManager asr ; //语音识别核心库
@Override
protected void onCreate ( Bundle savedInstanceState ) {
@ -209,6 +227,34 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
initResources ( ) ;
speech_sum ( ) ;
initView ( ) ;
txtResult = findViewById ( R . id . note_edit_view ) ;
asr = EventManagerFactory . create ( this , "asr" ) ;
//注册自己的输出事件类
asr . registerListener ( this ) ; // EventListener 中 onEvent方法
startBtn . setOnTouchListener ( new View . OnTouchListener ( ) {
@Override
public boolean onTouch ( View v , MotionEvent event ) {
int action = event . getAction ( ) ;
switch ( action ) {
case MotionEvent . ACTION_DOWN :
start ( ) ;
/ * mStartSpeechButton . setBackgroundResource (
R . drawable . bdspeech_btn_orangelight_pressed ) ; * /
break ;
case MotionEvent . ACTION_UP :
stop ( ) ;
/ * mStartSpeechButton . setBackgroundResource (
R . drawable . bdspeech_btn_orangelight_normal ) ; * /
break ;
default :
return false ;
}
return true ;
}
} ) ;
//根据id获取添加图片按钮
final ImageButton add_img_btn = ( ImageButton ) findViewById ( R . id . add_img_btn ) ;
@ -218,8 +264,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
public void onClick ( View view ) {
if ( ContextCompat . checkSelfPermission ( NoteEditActivity . this , Manifest . permission . WRITE_EXTERNAL_STORAGE ) ! = PackageManager . PERMISSION_GRANTED ) {
//没有授权进行权限申请
ActivityCompat . requestPermissions ( NoteEditActivity . this , new String [ ] { Manifest . permission . WRITE_EXTERNAL_STORAGE , Manifest . permission . READ_EXTERNAL_STORAGE } , GET_STORAGE_PERMISSION ) ; }
else {
ActivityCompat . requestPermissions ( NoteEditActivity . this , new String [ ] { Manifest . permission . WRITE_EXTERNAL_STORAGE , Manifest . permission . READ_EXTERNAL_STORAGE } , GET_STORAGE_PERMISSION ) ;
} else {
Log . d ( TAG , "onClick: click add image button" ) ;
//ACTION_GET_CONTENT: 允许用户选择特殊种类的数据,并返回(特殊种类的数据:照一张相片或录一段音)
Intent loadImage = new Intent ( Intent . ACTION_GET_CONTENT ) ;
@ -385,7 +431,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
getWindow ( ) . setSoftInputMode (
WindowManager . LayoutParams . SOFT_INPUT_STATE_HIDDEN
| WindowManager . LayoutParams . SOFT_INPUT_ADJUST_RESIZE ) ;
} else if ( TextUtils . equals ( Intent . ACTION_INSERT_OR_EDIT , intent . getAction ( ) ) ) {
} else if ( TextUtils . equals ( Intent . ACTION_INSERT_OR_EDIT , intent . getAction ( ) ) ) {
// New note
long folderId = intent . getLongExtra ( Notes . INTENT_EXTRA_FOLDER_ID , 0 ) ;
int widgetId = intent . getIntExtra ( Notes . INTENT_EXTRA_WIDGET_ID ,
@ -477,7 +523,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
} else {
mNoteHeaderHolder . tvAlertDate . setVisibility ( View . GONE ) ;
mNoteHeaderHolder . ivAlertIcon . setVisibility ( View . GONE ) ;
} ;
}
;
}
//路径字符串格式 转换为 图片image格式
@ -487,23 +534,23 @@ public class NoteEditActivity extends Activity implements OnClickListener,
String noteText = editable . toString ( ) ; //2.将note内容转换为字符串
int length = editable . length ( ) ; //内容的长度
//3.截取img片段 [local]+uri+[local], 提取uri
for ( int i = 0 ; i < length ; i + + ) {
for ( int j = i ; j < length ; j + + ) {
String img_fragment = noteText . substring ( i , j + 1 ) ; //img_fragment: 关于图片路径的片段
if ( img_fragment . length ( ) > 15 & & img_fragment . endsWith ( "[/local]" ) & & img_fragment . startsWith ( "[local]" ) ) {
for ( int i = 0 ; i < length ; i + + ) {
for ( int j = i ; j < length ; j + + ) {
String img_fragment = noteText . substring ( i , j + 1 ) ; //img_fragment: 关于图片路径的片段
if ( img_fragment . length ( ) > 15 & & img_fragment . endsWith ( "[/local]" ) & & img_fragment . startsWith ( "[local]" ) ) {
int limit = 7 ; //[local]为7个字符
//[local][/local]共15个字符, 剩下的为真正的path长度
int len = img_fragment . length ( ) - 15 ;
int len = img_fragment . length ( ) - 15 ;
//从[local]之后的len个字符就是path
String path = img_fragment . substring ( limit , limit + len ) ; //获取到了图片路径
String path = img_fragment . substring ( limit , limit + len ) ; //获取到了图片路径
Bitmap bitmap = null ;
Log . d ( TAG , "图片的路径是:" + path ) ;
Log . d ( TAG , "图片的路径是:" + path ) ;
try {
bitmap = BitmapFactory . decodeFile ( path ) ; //将图片路径解码为图片格式
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
if ( bitmap ! = null ) { //若图片存在
if ( bitmap ! = null ) { //若图片存在
Log . d ( TAG , "图片不为null" ) ;
ImageSpan imageSpan = new ImageSpan ( NoteEditActivity . this , bitmap ) ;
//4.创建一个SpannableString对象, 以便插入用ImageSpan对象封装的图像
@ -513,7 +560,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
spannableString . setSpan ( imageSpan , 0 , ss . length ( ) , Spannable . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
Log . d ( TAG , "Create spannable string success!" ) ;
Editable edit_text = noteEditText . getEditableText ( ) ;
edit_text . delete ( i , i + len + 15 ) ; //6.删掉图片路径的文字
edit_text . delete ( i , i + len + 15 ) ; //6.删掉图片路径的文字
edit_text . insert ( i , spannableString ) ; //7.在路径的起始位置插入图片
}
}
@ -559,7 +606,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private boolean inRangeOfView ( View view , MotionEvent ev ) {
int [ ] location = new int [ 2 ] ;
int [ ] location = new int [ 2 ] ;
view . getLocationOnScreen ( location ) ;
int x = location [ 0 ] ;
int y = location [ 1 ] ;
@ -595,7 +642,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
for ( int id : sFontSizeBtnsMap . keySet ( ) ) {
View view = findViewById ( id ) ;
view . setOnClickListener ( this ) ;
} ;
}
;
mSharedPrefs = PreferenceManager . getDefaultSharedPreferences ( this ) ;
mFontSizeId = mSharedPrefs . getInt ( PREFERENCE_FONT_SIZE , ResourceParser . BG_DEFAULT_FONT_SIZE ) ;
/ * *
@ -603,7 +651,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* The id may larger than the length of resources , in this case ,
* return the { @link ResourceParser # BG_DEFAULT_FONT_SIZE }
* /
if ( mFontSizeId > = TextAppearanceResources . getResourcesSize ( ) ) {
if ( mFontSizeId > = TextAppearanceResources . getResourcesSize ( ) ) {
mFontSizeId = ResourceParser . BG_DEFAULT_FONT_SIZE ;
}
mEditTextList = ( LinearLayout ) findViewById ( R . id . note_edit_list ) ;
@ -614,7 +662,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
protected void onPause ( ) {
super . onPause ( ) ;
if ( saveNote ( ) ) {
if ( saveNote ( ) ) {
Log . d ( TAG , "Note data was saved with length:" + mWorkingNote . getContent ( ) . length ( ) ) ;
}
clearSettingState ( ) ;
@ -631,7 +679,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return ;
}
intent . putExtra ( AppWidgetManager . EXTRA_APPWIDGET_IDS , new int [ ] {
intent . putExtra ( AppWidgetManager . EXTRA_APPWIDGET_IDS , new int [ ] {
mWorkingNote . getWidgetId ( )
} ) ;
@ -668,7 +716,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
public void onBackPressed ( ) {
if ( clearSettingState ( ) ) {
if ( clearSettingState ( ) ) {
return ;
}
@ -775,7 +823,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
DateTimePickerDialog d = new DateTimePickerDialog ( this , System . currentTimeMillis ( ) ) ;
d . setOnDateTimeSetListener ( new OnDateTimeSetListener ( ) {
public void OnDateTimeSet ( AlertDialog dialog , long date ) {
mWorkingNote . setAlertDate ( date , true ) ;
mWorkingNote . setAlertDate ( date , true ) ;
}
} ) ;
d . show ( ) ;
@ -840,7 +888,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
PendingIntent pendingIntent = PendingIntent . getBroadcast ( this , 0 , intent , 0 ) ;
AlarmManager alarmManager = ( ( AlarmManager ) getSystemService ( ALARM_SERVICE ) ) ;
showAlertHeader ( ) ;
if ( ! set ) {
if ( ! set ) {
alarmManager . cancel ( pendingIntent ) ;
} else {
alarmManager . set ( AlarmManager . RTC_WAKEUP , date , pendingIntent ) ;
@ -873,7 +921,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mEditTextList . removeViewAt ( index ) ;
NoteEditText edit = null ;
if ( index = = 0 ) {
if ( index = = 0 ) {
edit = ( NoteEditText ) mEditTextList . getChildAt ( 0 ) . findViewById (
R . id . et_edit_text ) ;
} else {
@ -890,7 +938,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
/ * *
* Should not happen , check for debug
* /
if ( index > mEditTextList . getChildCount ( ) ) {
if ( index > mEditTextList . getChildCount ( ) ) {
Log . e ( TAG , "Index out of mEditTextList boundrary, should not happen" ) ;
}
@ -910,7 +958,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
String [ ] items = text . split ( "\n" ) ;
int index = 0 ;
for ( String item : items ) {
if ( ! TextUtils . isEmpty ( item ) ) {
if ( ! TextUtils . isEmpty ( item ) ) {
mEditTextList . addView ( getListItem ( item , index ) ) ;
index + + ;
}
@ -975,7 +1023,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log . e ( TAG , "Wrong index, should not happen" ) ;
return ;
}
if ( hasText ) {
if ( hasText ) {
mEditTextList . getChildAt ( index ) . findViewById ( R . id . cb_edit_item ) . setVisibility ( View . VISIBLE ) ;
} else {
mEditTextList . getChildAt ( index ) . findViewById ( R . id . cb_edit_item ) . setVisibility ( View . GONE ) ;
@ -1101,13 +1149,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
e . printStackTrace ( ) ;
}
if ( bitmap ! = null ) {
if ( bitmap ! = null ) {
//3.根据Bitmap对象创建ImageSpan对象
Log . d ( TAG , "onActivityResult: bitmap is not null" ) ;
ImageSpan imageSpan = new ImageSpan ( NoteEditActivity . this , bitmap ) ;
String path = getPath ( this , originalUri ) ;
String path = getPath ( this , originalUri ) ;
//4.使用[local][/local]将path括起来, 用于之后方便识别图片路径在note中的位置
String img_fragment = "[local]" + path + "[/local]" ;
String img_fragment = "[local]" + path + "[/local]" ;
//创建一个SpannableString对象, 以便插入用ImageSpan对象封装的图像
SpannableString spannableString = new SpannableString ( img_fragment ) ;
spannableString . setSpan ( imageSpan , 0 , img_fragment . length ( ) , Spannable . SPAN_EXCLUSIVE_EXCLUSIVE ) ;
@ -1123,13 +1171,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
ContentResolver contentResolver = getContentResolver ( ) ;
ContentValues contentValues = new ContentValues ( ) ;
final long id = mWorkingNote . getNoteId ( ) ;
contentValues . put ( "snippet" , mWorkingNote . mContent ) ;
contentResolver . update ( Uri . parse ( "content://micode_notes/note" ) , contentValues , "_id=?" , new String [ ] { "" + id } ) ;
contentValues . put ( "snippet" , mWorkingNote . mContent ) ;
contentResolver . update ( Uri . parse ( "content://micode_notes/note" ) , contentValues , "_id=?" , new String [ ] { "" + id } ) ;
ContentValues contentValues1 = new ContentValues ( ) ;
contentValues1 . put ( "content" , mWorkingNote . mContent ) ;
contentResolver . update ( Uri . parse ( "content://micode_notes/data" ) , contentValues1 , "mime_type=? and note_id=?" , new String [ ] { "vnd.android.cursor.item/text_note" , "" + id } ) ;
contentValues1 . put ( "content" , mWorkingNote . mContent ) ;
contentResolver . update ( Uri . parse ( "content://micode_notes/data" ) , contentValues1 , "mime_type=? and note_id=?" , new String [ ] { "vnd.android.cursor.item/text_note" , "" + id } ) ;
} else {
} else {
Toast . makeText ( NoteEditActivity . this , "获取图片失败" , Toast . LENGTH_SHORT ) . show ( ) ;
}
break ;
@ -1153,7 +1201,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
final String type = split [ 0 ] ;
if ( "primary" . equalsIgnoreCase ( type ) ) {
return Environment . getExternalStorageDirectory ( ) + "/" + split [ 1 ] ;
return Environment . getExternalStorageDirectory ( ) + "/" + split [ 1 ] ;
}
}
// DownloadsProvider
@ -1163,8 +1211,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return getDataColumn ( context , contentUri , null , null ) ;
}
// MediaProvider
else
if ( isMediaDocument ( uri ) ) {
else if ( isMediaDocument ( uri ) ) {
final String docId = DocumentsContract . getDocumentId ( uri ) ;
final String [ ] split = docId . split ( ":" ) ;
final String type = split [ 0 ] ;
@ -1265,4 +1312,55 @@ public class NoteEditActivity extends Activity implements OnClickListener,
alertDialog2 = alertBuilder . create ( ) ;
alertDialog2 . show ( ) ;
}
private void start ( ) {
Toast . makeText ( NoteEditActivity . this , "请开始说话" , Toast . LENGTH_SHORT ) . show ( ) ;
Map < String , Object > params = new LinkedHashMap < > ( ) ; //传递Map<String,Object>的参数, 会将Map自动序列化为json
String event = null ;
event = SpeechConstant . ASR_START ;
params . put ( SpeechConstant . ACCEPT_AUDIO_VOLUME , false ) ; //回调当前音量
String json = null ;
json = new JSONObject ( params ) . toString ( ) ; //demo用json数据来做数据交换的方式
asr . send ( event , json , null , 0 , 0 ) ; // 初始化EventManager对象,这个实例只能创建一次, 就是我们上方创建的asr, 此处开始传入
}
private void stop ( ) {
//txtResult.append("停止识别: ASR_STOP");
asr . send ( SpeechConstant . ASR_STOP , null , null , 0 , 0 ) ; //此处停止
}
@Override
protected void onDestroy ( ) {
super . onDestroy ( ) ;
asr . send ( SpeechConstant . ASR_CANCEL , "{}" , null , 0 , 0 ) ;
asr . unregisterListener ( this ) ; //退出事件管理器
// 必须与registerListener成对出现, 否则可能造成内存泄露
}
public void onEvent ( String name , String params , byte [ ] data , int offset , int length ) {
String resultTxt = null ;
//Log.i(TAG, params);
if ( name . equals ( SpeechConstant . CALLBACK_EVENT_ASR_PARTIAL ) ) { //识别结果参数
if ( params . contains ( "\"final_result\"" ) ) { //语义结果值
try {
JSONObject json = new JSONObject ( params ) ;
String result = json . getString ( "best_result" ) ; //取得key的识别结果
resultTxt = result ;
} catch ( JSONException e ) {
e . printStackTrace ( ) ;
}
}
}
if ( resultTxt ! = null ) {
resultTxt + = "\n" ;
txtResult . append ( resultTxt ) ;
}
}
private void initView ( ) {
txtResult = findViewById ( R . id . note_edit_view ) ;
startBtn = findViewById ( R . id . listen ) ;
//stopBtn = findViewById(R.id.stop);
}
}