按delphi xe 的幫助檔案
uses
FMX.PhoneDialer;
type
TFormPhoneMain=class(TForm)
constructor Create(AOwner: TComponent); override;
procedure MyOnCallStateChanged(const ACallID: String; const ACallState: TCallState);
private
PhoneDialerService: IFMXPhoneDialerService;
{Form}
constructor TFormPhoneMain.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
TPlatformServices.Current.SupportsPlatformService(IFMXPhoneDialerService, IInterface(PhoneDialerService));
if Assigned(PhoneDialerService) then
PhoneDialerService.OnCallStateChanged:=MyOnCallStateChanged;
end;
procedure TFormPhoneMain.MyOnCallStateChanged(const ACallID: String; const ACallState: TCallState);
var
outText, s: String;
MyNotification: TNotification;
Begin
case ACallState of
TCallState.None:
outText:='無通話';
TCallState.Connected:
outText:='接通';
TCallState.Incoming:
outText:='來電';
TCallState.Dialing:
outText:='去電';
TCallState.Disconnected:
outText:='掛斷';
end;
s:='';
with UniQuery6 do
begin
Close;
ParamByName('V').Value:=ACallID;
Open;
if RecordCount>0 then
s:=FieldByName('User_Name').AsString+' '+outText
else
s:='未知號碼 '+outText;
end;
lblCallState.Text:='當前通話狀態 '+s+': '+ACallID;
FormActivate(nil);
if (outText='來電')or(outText='去電') then
begin
Timer1.Enabled:=True;
// Create an instance of TNotification
MyNotification:=NotificationCenter1.CreateNotification;
try
MyNotification.Name:='來電顯示';
// --- your code goes here ---
// Set the icon or notification number
MyNotification.Number:=18;
// Set the alert message
MyNotification.AlertBody:=lblCallState.Text;
// Note: You must send the notification to the notification center for the Icon Badge Number to be displayed.
NotificationCenter1.PresentNotification(MyNotification);
finally
MyNotification.DisposeOf;
end;
end
else
begin
Timer1.Enabled:=False;
NotificationCenter1.CancelNotification('來電顯示');
BringAppToFront(TJIntent.JavaClass.ACTION_MAIN);
end;
End;
結果在一些手機上可以正常獲取到來電,并把來電號碼與自建的電話號本匹配,發出來電資訊的通知;而大部分新的手機都監聽不到;網上查詢了一圈,的確有這樣的事情發生,JAVA用新建一個監聽來解決,但Delphi xe 目前資料太少,長時間沒找到解決方法,有人有解決辦法或者建議么?
參考網上一些相關的JAVA代碼,感覺通過自建監聽的方式,有可能能解決,分析了 Androidapi.JNI.Telephony 單元,發現其中的TJPhoneStateListener類應該能夠實作需求,它的定義是這樣的:
[JavaSignature('android/telephony/PhoneStateListener')]
JPhoneStateListener = interface(JObject)
['{50CE10E1-C584-4145-BC72-65BFA48BB281}']
procedure onCallForwardingIndicatorChanged(cfi: Boolean); cdecl;
procedure onCallStateChanged(state: Integer; incomingNumber: JString); cdecl;
procedure onCellInfoChanged(cellInfo: JList); cdecl;
procedure onCellLocationChanged(location: JCellLocation); cdecl;
procedure onDataActivity(direction: Integer); cdecl;
procedure onDataConnectionStateChanged(state: Integer); cdecl; overload;
procedure onDataConnectionStateChanged(state: Integer; networkType: Integer); cdecl; overload;
procedure onMessageWaitingIndicatorChanged(mwi: Boolean); cdecl;
procedure onServiceStateChanged(serviceState: JServiceState); cdecl;
procedure onSignalStrengthChanged(asu: Integer); cdecl;//Deprecated
procedure onSignalStrengthsChanged(signalStrength: JSignalStrength); cdecl;
end;
TJPhoneStateListener = class(TJavaGenericImport<JPhoneStateListenerClass, JPhoneStateListener>) end;現在問題來了,我該如何使用呢?
uj5u.com熱心網友回復:
應該是權限管理的問題,見:https://newsgroups.embarcadero.com/thread.jspa?threadID=245771uj5u.com熱心網友回復:
Delphi xe 目前資料太少uj5u.com熱心網友回復:
謝謝,我試試這個帖子給出的解決辦法,懷疑是安卓6.0版本權限給不到,需要顯式給權限;另外,就是認為SDK版本太低了,要升級v4檔案
uj5u.com熱心網友回復:
usesAndroidapi.Helpers, Androidapi.JNIBridge, Androidapi.JNI.JavaTypes;
...
var
LPermissions: TJavaObjectArray<JString>;
begin
LPermissions := TJavaObjectArray<JString>.Create(1);
LPermissions.Items[0] := StringToJString('android.permission.READ_PHONE_STATE');
TAndroidHelper.Activity.requestPermissions(LPermissions, 0);
end;
現在的問題是,因為Delphi中的Activity沒有實作onRequestPermissionsResult,所以你不知道
用戶是否真正授予了權限; 至少不是通過那種異步的方法。解決這個問題的方法可能是
稍后在某個時間點檢查權限。問題是
在Delphi RTL中沒有匯入適當的Java類(PermissionChecker)。我只是碰巧自己做了這個匯入,并創建了
下面的代碼:
type
TAndroidPermissions = class(TObject)
public
const CAMERA = 'android.permission.CAMERA';
const RECORD_AUDIO = 'android.permission.RECORD_AUDIO';
const READ_CONTACTS = 'android.permission.READ_CONTACTS';
const READ_PHONE_STATE = 'android.permission.READ_PHONE_STATE';
public
class function CheckPermission(const APermissionName: string): Boolean; static;
end;
implementation
uses
Androidapi.JNI.JavaTypes, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNIBridge, Androidapi.Helpers;
type
JPermissionCheckerClass = interface(JObjectClass)
['{FC8D7A0B-078A-4DBB-B115-17E6F0E7CA18}']
{class} function _GetPERMISSION_DENIED: Integer; cdecl;
{class} function _GetPERMISSION_DENIED_APP_OP: Integer; cdecl;
{class} function _GetPERMISSION_GRANTED: Integer; cdecl;
{class} function checkCallingOrSelfPermission(P1: JContext; P2: JString): Integer; cdecl;
{class} function checkCallingPermission(P1: JContext; P2: JString; P3: JString): Integer; cdecl;
{class} function checkPermission(P1: JContext; P2: JString; P3: Integer; P4: Integer; P5: JString): Integer; cdecl;
{class} function checkSelfPermission(P1: JContext; P2: JString): Integer; cdecl;
{class} property PERMISSION_DENIED: Integer read _GetPERMISSION_DENIED;
{class} property PERMISSION_DENIED_APP_OP: Integer read _GetPERMISSION_DENIED_APP_OP;
{class} property PERMISSION_GRANTED: Integer read _GetPERMISSION_GRANTED;
end;
[JavaSignature('android/support/v4/content/PermissionChecker')]
JPermissionChecker = interface(JObject)
['{AF30C4BE-CF3B-4AE0-A274-D96FBC08728E}']
end;
TJPermissionChecker = class(TJavaGenericImport<JPermissionCheckerClass, JPermissionChecker>) end;
{ TAndroidPermissions }
class function TAndroidPermissions.CheckPermission(const APermissionName: string): Boolean;
begin
Result := TJPermissionChecker.JavaClass.checkSelfPermission(TAndroidHelper.Context, StringToJString(APermissionName))
= TJPermissionChecker.JavaClass.PERMISSION_GRANTED;
end;
這可以這樣呼叫:
TAndroidPermissions.CheckPermission(TAndroidPermissions.READ_PHONE_STATE);
這可能是您現在的臨時解決方案,但使用onRequestPermissionsResult會更可靠。
Brian Long最初的方法是“覆寫”一個原生的Activity方法,例如他在這里所做的:
http : //blong.com/Articles/DelphiXE7NFC/NFC.htm
可能是一個潛在的解決方案,然而Embarcadero真的應該使它成為FMXNativeActivity的一部分,因為
隨著時間的推移,這個問題會越來越頻繁地出現。
uj5u.com熱心網友回復:
唉,不能解決,TAndroidHelper.Activity.requestPermissions(LPermissions, 0);顯式申請權限提示缺少requestPermissions這個程序,檢查權限,顯示沒有找到Java類(PermissionChecker)。有高手能幫忙看下么?uj5u.com熱心網友回復:
去英巴官網論壇問了嗎?uj5u.com熱心網友回復:
EMB沒有完整翻譯Android API,但是提供了一個工具java2op.exe,可以翻譯Android API,另外也有人翻譯了完整的各Android版本SDK介面檔案:https://github.com/FMXExpress/android-object-pascal-wrapper/uj5u.com熱心網友回復:
@早打大打打核戰爭如果用CB寫安卓程式,Android API的Delphi介面檔案還要再翻譯為C++格式的嗎?
uj5u.com熱心網友回復:
不用,有.pas就行,Delphi編譯器(CB自帶)能自動生成給CB用的.hpp和.lib。uj5u.com熱心網友回復:
@早打大打打核戰爭那實際編程要把.pas檔案加入工程,編譯生成.hpp和.lib后,再把.pas檔案去掉,包含.hpp頭檔案后呼叫API?
uj5u.com熱心網友回復:
這樣工程量就太大了,而且我印象有人發過文章,說翻譯過來,幾萬條代碼,還不是說立馬就可以用的,查錯會要老命.我做個小程式玩玩,還范不著這么大動干戈,但不管怎么說,還是要謝謝你的幫助.uj5u.com熱心網友回復:
https://github.com/FMXExpress/android-object-pascal-wrapper/blob/master/android-26/android.app.Activity.pas 我在他的檔案里的確找到了給權限的相關內容procedure requestPermissions(permissions : TJavaArray<JString>; requestCode : Integer) ; cdecl;
procedure onRequestPermissionsResult(requestCode : Integer; permissions : TJavaArray<JString>; grantResults : TJavaArray<Integer>) ; cdecl;
我的問題是,我只下載這個PAS,并把這個PAS加載到工程檔案里,可行么?還是要其他什么操作?
uj5u.com熱心網友回復:
光這個檔案肯定不行,你看它uses了多少單元。你下載后把某個版本的SDK介面,比如android-26,復制出來,然后添加到專案的查找路徑就可以使用了。轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/44319.html
標籤:VCL組件開發及應用
