Android实例-调用GOOGLE的TTS实现文字转语音(XE7+小米2)(XE10.1+小米5)
相关资料:
注意:在手机上必须选安装文字转语音引擎“google Text To Speech”
地址:http://www.shouji56.com/soft/GoogleWenZiZhuanYuYinYinQingGoogleTexttoSpeech_3864/
结果总结:
XE10.1 + 小米手机5 = 通过测试
首先手机上必须安装语音包:
1.“google Text To Speech” (不知为什么我的只发英文)
2.“度秘语音引擎3.0” (中英都可以发音)
3.“科大讯飞语音引擎3.0”(中英都可以发音)
4.APK发音使用的是当前语音包
5.小米手机5-设置-更多设置-语言和输入法-文字转语音(TTS)输出
1. 新建一个单元Androidapi.JNI.TTS
{*******************************************************}
{ }
{ CodeGear Delphi Runtime Library }
{ Copyright(c) 2013 Jeff Overcash }
{ }
{*******************************************************}
{ Delphi trnslation for TTS Android Java classes from }
{ http://developer.android.com/reference/android/speech/tts/package-summary.html }
unit Androidapi.JNI.TTS;
interface
uses Androidapi.JNIBridge,
Androidapi.JNI.JavaTypes,
Androidapi.JNI.Os,
Androidapi.JNI.App,
Androidapi.JNI.GraphicsContentViewText;
type
{Forward declarations}
JSynthesisCallback = interface; // android.speech.tts.SynthesisCallback
JSynthesisRequest = interface; // android.speech.tts.SynthesisRequest
JTextToSpeech = interface; // android.speech.tts.TextToSpeech
JTextToSpeech_Engine = interface; // android.speech.tts.TextToSpeech$Engine
JTextToSpeech_EngineInfo = interface; //android.speech.tts.TextToSpeech$EngineInfo
JTextToSpeech_OnInitListener = interface; // android.speech.tts.TextToSpeech$OnInitListener
JTextToSpeech_OnUtteranceCompletedListener = interface; // android.speech.tts.TextToSpeech$OnUtteranceCompletedListener
JTextToSpeechService = interface; // android.speech.tts.TextToSpeechService
JUtteranceProgressListener = interface; // android.speech.tts.UtteranceProgressListener
JSynthesisCallbackClass = interface(IJavaClass)
['{3B30766E-A43B-4005-BE92-472CD075F325}']
end;
[JavaSignature('android/speech/tts/SynthesisCallback')]
JSynthesisCallback = interface(IJavaInstance)
['{190C13DE-BC7E-44CE-94F6-4AF1A84A4612}']
function audioAvailable(buffer: TJavaArray<byte>; offset: Integer; length: Integer): Integer; cdecl;
function done: Integer; cdecl;
procedure error; cdecl;
function getMaxBufferSize: Integer; cdecl;
function start(sampleRateInHz: Integer; audioFormat: Integer; channelCount: Integer): Integer; cdecl;
end;
TJSynthesisCallback = class(TJavaGenericImport<JSynthesisCallbackClass, JSynthesisCallback>) end;
JSynthesisRequestClass = interface(JObjectClass)
['{AE41459D-42C6-4E66-B174-F6FA5216A1DA}']
{ Method }
function init(text: JString; params: JBundle): JSynthesisRequest;
end;
[JavaSignature('android/speech/tts/SynthesisRequest')]
JSynthesisRequest = interface(JObject)
['{1963DAD8-C58F-4868-BF8A-B43AE7A14145}']
function getCountry: JString; cdecl;
function getLanguage: JString; cdecl;
function getParams: JBundle; cdecl;
function getPitch: Integer; cdecl;
function getSpeechRate: Integer; cdecl;
function getText: JString; cdecl;
function getVariant: JString; cdecl;
end;
TJSynthesisRequest = class(TJavaGenericImport<JSynthesisRequestClass, JSynthesisRequest>) end;
JTextToSpeechClass = interface(JObjectClass)
['{0E2C5E49-95BE-4F19-BCCD-21960D03E957}']
{ Property Methods }
function _GetACTION_TTS_QUEUE_PROCESSING_COMPLETED: JString;
function _GetERROR: Integer;
function _GetLANG_AVAILABLE: Integer;
function _GetLANG_COUNTRY_AVAILABLE: Integer;
function _GetLANG_COUNTRY_VAR_AVAILABLE: Integer;
function _GetLANG_MISSING_DATA: Integer;
function _GetLANG_NOT_SUPPORTED: Integer;
function _GetQUEUE_ADD: Integer;
function _GetQUEUE_FLUSH: Integer;
function _GetSUCCESS: Integer;
{ Methods }
function init(contect: JContext; listener: JTextToSpeech_OnInitListener) : JTextToSpeech; cdecl; overload;
function init(context: JContext; listener: JTextToSpeech_OnInitListener; engine: JString): JTextToSpeech; overload;
{ Properties }
property ACTION_TTS_QUEUE_PROCESSING_COMPLETED: JString read _GetACTION_TTS_QUEUE_PROCESSING_COMPLETED;
property ERROR: Integer read _GetERROR;
property LANG_AVAILABLE: Integer read _GetLANG_AVAILABLE;
property LANG_COUNTRY_AVAILABLE: Integer read _GetLANG_COUNTRY_AVAILABLE;
property LANG_COUNTRY_VAR_AVAILABLE: Integer read _GetLANG_COUNTRY_VAR_AVAILABLE;
property LANG_MISSING_DATA: Integer read _GetLANG_MISSING_DATA;
property LANG_NOT_SUPPORTED: Integer read _GetLANG_NOT_SUPPORTED;
property QUEUE_ADD: Integer read _GetQUEUE_ADD;
property QUEUE_FLUSH: Integer read _GetQUEUE_FLUSH;
property SUCCESS: Integer read _GetSUCCESS;
end;
[JavaSignature('android/speech/tts/TextToSpeech')]
JTextToSpeech = interface(JObject)
['{E1D06364-F967-4381-B178-EEDD42C203C7}']
function addEarcon(earcon: JString; filename: JString): Integer; cdecl; overload;
function addEarcon(earcon: JString; packagename: JString; resourceID: Integer): Integer; cdecl; overload;
function addSpeech(text: JString; filename: JString): Integer; cdecl; overload;
function addSpeech(text: JString; packagename: JString; resourceID: Integer) : Integer; cdecl; overload;
function areDefaultsEnforced: Boolean; cdecl;
function getDefaultEngine: JString; cdecl;
function getEngines: JList; cdecl;
function getFeatures(locale: JLocale): JSet; cdecl;
function getLanguage: JLocale; cdecl;
function isLanguageAvailable(loc: JLocale): Integer; cdecl;
function isSpeaking: Boolean; cdecl;
function playEarcon(earcon: JString; queueMode: Integer; params: JHashMap) : Integer; cdecl;
function playSilence(durationInMs: Int64; queueMode: Integer; params: JHashMap): Integer; cdecl;
function setEngineByPackageName(enginePackageName: JString): Integer; cdecl;
function setLanguage(loc: JLocale): Integer; cdecl;
function setOnUtteranceCompletedListener(listener: JTextToSpeech_OnUtteranceCompletedListener): Integer; cdecl;
function setOnUtteranceProgressListener(listener: JUtteranceProgressListener): Integer; cdecl;
function setPitch(pitch: Single): Integer; cdecl;
function setSpeechRate(speechRate: Single): Integer; cdecl;
procedure shutdown; cdecl;
function speak(text: JString; queueMode: Integer; params: JHashMap) : Integer; cdecl;
function stop: Integer; cdecl;
function synthesizeToFile(text: JString; params: JHashMap; filename: String) : Integer; cdecl;
end;
TJTextToSpeech = class(TJavaGenericImport<JTextToSpeechClass, JTextToSpeech>) end;
JTextToSpeech_EngineClass = interface(JObjectClass)
['{8516EA75-A410-4EEE-8281-9ABCE1577F46}']
{ Property Methods }
function _GeCHECK_VOICE_DATA_PASS: Integer;
function _GetACTION_CHECK_TTS_DATA: JString;
function _GetACTION_INSTALL_TTS_DATA: JString;
function _GetACTION_TTS_DATA_INSTALLED: JString;
function _GetCHECK_VOICE_DATA_BAD_DATA: Integer;
function _GetCHECK_VOICE_DATA_FAIL: Integer;
function _GetCHECK_VOICE_DATA_MISSING_DATA: Integer;
function _GetCHECK_VOICE_DATA_MISSING_VOLUME: Integer;
function _GetDEFAULT_STREAM: Integer;
function _GetEXTRA_AVAILABLE_VOICES: JString;
function _GetEXTRA_CHECK_VOICE_DATA_FOR: JString;
function _GetEXTRA_TTS_DATA_INSTALLED: JString;
function _GetEXTRA_UNAVAILABLE_VOICES: JString;
function _GetEXTRA_VOICE_DATA_FILES: JString;
function _GetEXTRA_VOICE_DATA_FILES_INFO: JString;
function _GetEXTRA_VOICE_DATA_ROOT_DIRECTORY: JString;
function _GetINTENT_ACTION_TTS_SERVICE: JString;
function _GetKEY_FEATURE_EMBEDDED_SYNTHESIS: JString;
function _GetKEY_FEATURE_NETWORK_SYNTHESIS: JString;
function _GetKEY_PARAM_PAN: JString;
function _GetKEY_PARAM_STREAM: JString;
function _GetKEY_PARAM_UTTERANCE_ID: JString;
function _GetKEY_PARAM_VOLUME: JString;
function _GetSERVICE_META_DATA: JString;
{ Methods }
function init: JTextToSpeech_Engine;
{ Properties }
property ACTION_CHECK_TTS_DATA: JString read _GetACTION_CHECK_TTS_DATA;
property ACTION_INSTALL_TTS_DATA: JString read _GetACTION_INSTALL_TTS_DATA;
property ACTION_TTS_DATA_INSTALLED: JString read _GetACTION_TTS_DATA_INSTALLED;
property CHECK_VOICE_DATA_BAD_DATA: Integer read _GetCHECK_VOICE_DATA_BAD_DATA;
property CHECK_VOICE_DATA_FAIL: Integer read _GetCHECK_VOICE_DATA_FAIL;
property CHECK_VOICE_DATA_MISSING_DATA: Integer read _GetCHECK_VOICE_DATA_MISSING_DATA;
property CHECK_VOICE_DATA_MISSING_VOLUME: Integer read _GetCHECK_VOICE_DATA_MISSING_VOLUME;
property CHECK_VOICE_DATA_PASS: Integer read _GeCHECK_VOICE_DATA_PASS;
property DEFAULT_STREAM: Integer read _GetDEFAULT_STREAM;
property EXTRA_AVAILABLE_VOICES: JString read _GetEXTRA_AVAILABLE_VOICES;
property EXTRA_CHECK_VOICE_DATA_FOR: JString read _GetEXTRA_CHECK_VOICE_DATA_FOR;
property EXTRA_TTS_DATA_INSTALLED: JString read _GetEXTRA_TTS_DATA_INSTALLED;
property EXTRA_UNAVAILABLE_VOICES: JString read _GetEXTRA_UNAVAILABLE_VOICES;
property EXTRA_VOICE_DATA_FILES: JString read _GetEXTRA_VOICE_DATA_FILES;
property EXTRA_VOICE_DATA_FILES_INFO: JString read _GetEXTRA_VOICE_DATA_FILES_INFO;
property EXTRA_VOICE_DATA_ROOT_DIRECTORY: JString read _GetEXTRA_VOICE_DATA_ROOT_DIRECTORY;
property INTENT_ACTION_TTS_SERVICE: JString read _GetINTENT_ACTION_TTS_SERVICE;
property KEY_FEATURE_EMBEDDED_SYNTHESIS: JString read _GetKEY_FEATURE_EMBEDDED_SYNTHESIS;
property KEY_FEATURE_NETWORK_SYNTHESIS: JString read _GetKEY_FEATURE_NETWORK_SYNTHESIS;
property KEY_PARAM_PAN: JString read _GetKEY_PARAM_PAN;
property KEY_PARAM_STREAM: JString read _GetKEY_PARAM_STREAM;
property KEY_PARAM_UTTERANCE_ID: JString read _GetKEY_PARAM_UTTERANCE_ID;
property KEY_PARAM_VOLUME: JString read _GetKEY_PARAM_VOLUME;
property SERVICE_META_DATA: JString read _GetSERVICE_META_DATA;
end;
JTextToSpeech_Engine = interface(JObject)
['{5BAC3048-CB0C-4DC4-AF62-D0D9AE4394CF}']
end;
TJTextToSpeech_Engine = class(TJavaGenericImport<JTextToSpeech_EngineClass, JTextToSpeech_Engine>) end;
JTextToSpeech_EngineInfoClass = interface(JObjectClass)
['{8297AD59-5A6F-4867-A185-CA09BAD90159}']
{Methods}
function init : JTextToSpeech_EngineInfo;
end;
JTextToSpeech_EngineInfo = interface(JObject)
['{204B30D8-6E25-4531-847D-18588D48D9BF}']
{property Methods}
function _Geticon: integer;
function _Getlabel: JString;
function _Getname: JString;
procedure _Seticon(const Value: integer);
procedure _Setlabel(const Value: JString);
procedure _Setname(const Value: JString);
{Properties}
property icon : integer read _Geticon write _Seticon;
property _label : JString read _Getlabel write _Setlabel;
property name : JString read _Getname write _Setname;
end;
TJTextToSpeech_EngineInfo = class(TJavaGenericImport<JTextToSpeech_EngineInfoClass, JTextToSpeech_EngineInfo>) end;
JTextToSpeech_OnInitListenerClass = interface(IJavaClass)
['{58D32EFB-6528-4EC6-BA4F-28B22FE8E573}']
end;
[JavaSignature('android/speech/tts/TextToSpeech$OnInitListener')]
JTextToSpeech_OnInitListener = interface(IJavaInstance)
['{027DA109-680A-4A69-905D-F62E2BD1282F}']
procedure onInit(status: Integer); cdecl;
end;
TJTextToSpeech_OnInitListener = class(TJavaGenericImport<JTextToSpeech_OnInitListenerClass,JTextToSpeech_OnInitListener>) end;
JTextToSpeech_OnUtteranceCompletedListenerClass = interface(IJavaClass)
['{0A608BB9-A6BF-4746-8419-9317AD625DFA}']
end;
[JavaSignature('android/speech/tts/TextToSpeech$OnUtteranceCompletedListener')]
JTextToSpeech_OnUtteranceCompletedListener = interface(IJavaInstance)
['{00439F2B-E73C-4B93-A9E3-832AE3CC1D5F}']
procedure onUtteranceCompleted(utteranceID: JString); cdecl;
end;
TJTextToSpeech_OnUtteranceCompletedListener = class(TJavaGenericImport<JTextToSpeech_OnUtteranceCompletedListenerClass, JTextToSpeech_OnUtteranceCompletedListener>) end;
JTextToSpeechServiceClass = interface(JServiceClass)
['{6BCC6ADC-CBCB-4515-A5C3-E33F9787EEC2}']
function init : JTextToSpeechService;
end;
[JavaSignature('android/speech/tts/TextToSpeechService')]
JTextToSpeechService = interface(JService)
['{EE3943B6-88DC-488B-9E10-E0FA9914708D}']
function onGetFeaturesForLanguage(lang : JString; country : JString; variant : JString) : JSet; cdecl;
function onGetLanguage : TJavaArray<JString>; cdecl;
function onIsLanguageAvailable(lang : JString; country : JString; variant : JString) : Integer; cdecl;
function onLoadLanguage(lang : JString; country : JString; variant : JString) : Integer; cdecl;
procedure onStop; cdecl;
procedure onSynthesizeText(request : JSynthesisRequest; callback : JSynthesisCallback); cdecl;
end;
TJTextToSpeechService = class(TJavaGenericImport<JTextToSpeechServiceClass, JTextToSpeechService>) end;
JUtteranceProgressListenerClass = interface(JObjectClass)
['{0870532F-6FD7-4B1F-9DEF-B53F0095C98A}']
{ Method }
function init: JUtteranceProgressListener;
end;
[JavaSignature('android/speech/tts/UtteranceProgressListener')]
JUtteranceProgressListener = interface(JObject)
['{8B03499D-0B26-4F36-90E8-F724BD78DB0C}']
procedure onDone(utteranceID: JString); cdecl;
procedure onError(utteranceID: JString); cdecl;
procedure onStart(utteranceID: JString); cdecl;
end;
TJUtteranceProgressListener = class(TJavaGenericImport<JUtteranceProgressListenerClass, JUtteranceProgressListener>) end;
implementation
end.
2.实例代码
{********************************************************}
{ XE10.1 + 小米手机5 = 通过测试 }
{ 首先手机上必须安装语音包 }
{ 语音包有 }
{ 1.“google Text To Speech” (不知为什么我的只发英文) }
{ 2.“度秘语音引擎3.0” (中英都可以发音) }
{ 3.“科大讯飞语音引擎3.0”(中英都可以发音) }
{ 4.APK发音使用的是当前语音包 }
{ 5.设置-更多设置-语言和输入法-文字转语音(TTS)输出 }
{********************************************************}
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ScrollBox,
FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls,
//需要引入的单元
FMX.Helpers.Android,//引
Androidapi.Helpers,//引入
Androidapi.JNIBridge,//引入
Androidapi.Jni.JavaTypes,//引入
Androidapi.JNI.TTS;//引入
type
TForm1 = class(TForm)
Button1: TButton;//发音
Button2: TButton;//初始化
Memo1: TMemo;//内容,可以是英语,可以是中文
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
type
//倾听者
TttsOnInitListener = class(TJavaLocal, JTextToSpeech_OnInitListener)
private
FParent: TForm1;
public
constructor Create(AParent: TForm1);
procedure onInit(status: Integer); cdecl;
end;
private
{ Private declarations }
ttsListener: TttsOnInitListener;//倾听者私有对象
TTS: JTextToSpeech;//文字TO言语
procedure SpeakOut;//说话
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{$R *.LgXhdpiPh.fmx ANDROID}
//发音
procedure TForm1.Button1Click(Sender: TObject);
begin
SpeakOut;
end;
//初始化
procedure TForm1.Button2Click(Sender: TObject);
begin
TTS := TJTextToSpeech.JavaClass.init(SharedActivityContext, ttsListener);
end;
//建立私有对象
constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
ttsListener := TttsOnInitListener.Create(self);
end;
//释放对象
destructor TForm1.Destroy;
begin
if Assigned(TTS) then
begin
TTS.stop;
TTS.shutdown;
TTS := nil;
end;
ttsListener := nil;
inherited;
end;
//把要朗读的文字指定给 TTS 引擎
procedure TForm1.SpeakOut;
var
text: JString;
begin
text := StringToJString(Memo1.Lines.text);
TTS.speak(text, TJTextToSpeech.JavaClass.QUEUE_FLUSH, nil);
end;
{ TForm1.TttsOnInitListener }
constructor TForm1.TttsOnInitListener.Create(AParent: TForm1);
begin
inherited Create;
FParent := AParent;
end;
procedure TForm1.TttsOnInitListener.onInit(status: Integer);
var
Result: Integer;
begin
if (status = TJTextToSpeech.JavaClass.SUCCESS) then
begin
Result := FParent.TTS.setLanguage(TJLocale.JavaClass.US); // 这是指定这美语
if (Result = TJTextToSpeech.JavaClass.LANG_MISSING_DATA) or
(Result = TJTextToSpeech.JavaClass.LANG_NOT_SUPPORTED) then
//这里在XE10.1中提示“只能在主线程中使用此提示”
//ShowMessage('不支持这种语言!')
else
begin
FParent.Button1.Enabled := True;
FParent.Button2.Enabled := False;
end;
end
else
begin
//ShowMessage('初始化失败!');
end;
end;
end.
Android实例-调用GOOGLE的TTS实现文字转语音(XE7+小米2)(XE10.1+小米5)的更多相关文章
- Android实例-调用GOOGLE的TTS实现文字转语音(XE7+小米2)(无图)
注意:在手机上必须选安装文字转语音引擎“google Text To Speech”地址:http://www.shouji56.com/soft/GoogleWenZiZhuanYuYinYinQi ...
- 调用GOOGLE的TTS实现文字转语音(XE7+小米2)(XE10.1+小米5)
相关资料: 注意:在手机上必须选安装文字转语音引擎“google Text To Speech”地址:http://www.shouji56.com/soft/GoogleWenZiZhuanYuYi ...
- Android实例-调用系统APP(XE10+小米2)
相关资料:群号383675978 实例源码: unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, Sys ...
- Android实例-打电话、发短信和邮件,取得手机IMEI号(XE8+小米2)
结果: 1.不提示发短信卡住,点击没有反映,我猜想,可能是因为我用的是小米手机吧. 2.接收短信报错,我猜想可能是我改了里面的方法吧(哪位大神了解,求指教). 3.project -->opti ...
- Android文字转语音引擎(TTS)使用
百度网盘下载地址 密码:3si0资源来源:https://blog.csdn.net/Sqq_yj/article/details/82460580?utm_source=blogxgwz4 简单比较 ...
- Android技术分享-文字转语音并朗读
Android技术分享-文字转语音并朗读 最近在做一个项目,其中有一个功能是需要将文本转换成语音并播放出来.下面我将我的做法分享一下. 非常令人开心的是,Android系统目前已经集成了TTS,提供了 ...
- speech sdk 文字转语音
1.下载SDK包 https://www.microsoft.com/en-us/download/details.aspx?id=10121 2.直接上代码 // SpeechRecognition ...
- Android 文字转语音(TTS)
1.介绍 2.xml文件布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xml ...
- Android App调用MediaRecorder实现录音功能的实例【转】
本文转载自:http://www.jb51.net/article/82281.htm 这篇文章主要介绍了Android App调用MediaRecorder实现录音功能的实例,MediaRecord ...
随机推荐
- hadoop资料
1."Hadoop.Operations.pdf.zip" http://vdisk.weibo.com/s/vDOQs6xMAQH6 2."Hadoop权威指南(中文版 ...
- C# WinForm开发系列 - DataGrid/DataGridView
在WinForm开发中,DataGrid/DataGridView被广泛使用于绑定数据库中数据进行呈现.整理一些关于DataGrid/DataGridView使用的文章,涉及DataGrid/Data ...
- TripleDES之C#和PHP之间加密解密
在C#常用加密解密一文中,介绍了几个加密解密方法,其中有个如何使用对称加密算法DES,此次说下DES的升级版,TripleDES. DES和TripleDES之间的关系可以参考下面的博文. 对称加密D ...
- 【Spring】SpringMVC之上传文件
这里笔者介绍利用SpringMVC上传图片的操作. 步骤 1. 引入jar文件 不仅需要导入开发SpringMVC相关的包,还需要导入 commons-fileupload-1.2.1.jar 和 ...
- mybatis自定义插件动态修改sql语句
step1:定义Interceptor实现org.apache.ibatis.plugin.Interceptor import org.apache.commons.logging.Log; imp ...
- 巧用linux服务器的/dev/shm/
巧用linux服务器的/dev/shm/,如果合理使用,可以避开磁盘IO不给力,提高网站访问速度. 首先让我们认识一下,什么是tmpfs和/dev/shm/? tmpfs是Linux/Unix系统上的 ...
- 新建MVC3 编译出现 System.Web.Mvc.ModelClientValidationRule
我在vs2010 新建一个Mvc3项目,编译报一下错误: 错误 1 'c:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\A ...
- golang 学习笔记 ---make/copy/append
package main import ( "fmt" ) func main() { a := [...]int{0, 1, 2, 3, 4, 5, 6, 7} s := mak ...
- haproxy 关闭ssl3
在使用的过程中,我们发现在用IE浏览器的时候 我们设置成 然后我们的网站会出现部分页面不出来 然后我们也发现在扫面网站链接的时候 所以当务之急是关闭ssl3 我这里的反向代理使用的是haproxy 版 ...
- 对 /sbin/nologin 的理解
对 /sbin/nologin 的理解 系统账号的shell使用 /sbin/nologin ,此时无法登陆系统,即使给了密码也不行. 所谓“无法登陆”指的仅是这个用户无法使用bash或其他she ...