자유롭게 질의 및 응답을 할 수 있는 게시판입니다. 개발자 여러분의 답변이 큰 도움이 됩니다.
- 제품설치/등록 오류 문의: 설치/등록 Q&A 이용 (제품 구매 고객 한정)
Delphi 안드로이드 ForeGround Service 사용법
2019.01.28 14:06
본 게시판은 개발자들이 자유롭게 질문과 답변을 공유하는 게시판입니다.
* 따라서 최대한 정중하게 질문을 올려 주세요.
* 질문을 상세히 작성해 주실 수록 좋은 답변이 올라 옵니다.
* 다른 분들도 참고할 수 있도록 결과 댓글 필수(또는 감사 댓글)
(결과 댓글을 달지 않는 경우 다음 질문에 대한 답변이 달리지 않는 불이익이 있을 수 있습니다.)
-----------------------------------------------------------------------------------------------
안녕하세요
안드로이드 앱개발 새내기 입니다.
다름이 아니라 이번에 개발하는 어플에 한가지 문제점이 있어 문의 드립니다.
델파이 10.2 도쿄버전으로 개발중입니다.
서버와 스마트폰어플로 TCP/IP 통신을 하는게 주된 어플리케이션입니다.
근데 안드로이드5 이상 버전에서는 스마트폰의 홈버튼으로 어플을 감춰놓으면 3~4분후에 종료됩니다.
종료와 동시에 TCP/IP 커넥션이 끊기게 되어 개발된 앱을 사용할수가 없는 상황입니다.
구글검색으로 한가지 방법을 찾아 StartForegroundService라는 안드로이드 서비스를 찾아냈지만,
델파이로 사용된 정확한 예시소스를 찾을수 없어 계속 실패하고 있습니다.
혹시 자바가 아닌 델파이로 구현된 StartForeground 기능을 알고계시다면 도움을 주시길 부탁드립니다.
구글검색으로 찾았던 소스도 같이 올려드립니다.
type
TGeneratorUniqueID = class
const
SETTINGS_NOTIFICATION_UNIQUE_ID = 'SETTINGS_NOTIFICATION_UNIQUE_ID2';
strict private
class var FNextUniqueID: Int64;
public
class constructor Create;
class function GenerateID: Integer;
end;
const
FMX_NOTIFICATION_CENTER = 'FMX_NOTIFICATION_CENTER2';
class constructor TGeneratorUniqueID.Create;
var
Preference: JSharedPreferences;
begin
Preference := SharedActivity.getSharedPreferences(StringToJString(FMX_NOTIFICATION_CENTER), TJContext.JavaClass.MODE_PRIVATE);
FNextUniqueID := Preference.getInt(StringToJString(SETTINGS_NOTIFICATION_UNIQUE_ID), 0);
end;
class function TGeneratorUniqueID.GenerateID: Integer;
var
PreferenceEditor: JSharedPreferences_Editor;
Preference: JSharedPreferences;
begin
Preference := SharedActivity.getPreferences(TJContext.JavaClass.MODE_PRIVATE);
PreferenceEditor := Preference.edit;
try
PreferenceEditor.putInt(StringToJString(SETTINGS_NOTIFICATION_UNIQUE_ID), FNextUniqueID);
finally
PreferenceEditor.commit;
end;
Result := FNextUniqueID;
Inc(FNextUniqueID);
end;
//* My code
procedure TFormMain.SetForeground;
var
Service: JService;
notification: JNotification;
NotificationCompat_Builder: JNotificationCompat_Builder;
Intent: JIntent;
begin
NotificationCompat_Builder := TJNotificationCompat_Builder.Create;
NotificationCompat_Builder := NotificationCompat_Builder.setSmallIcon(SharedActivityContext.getApplicationInfo.icon);
NotificationCompat_Builder := NotificationCompat_Builder.setContentTitle(StrToJCharSequence(GetApplicationTitle));
NotificationCompat_Builder := NotificationCompat_Builder.setContentText(StrToJCharSequence('Body'));
notification := NotificationCompat_Builder.build;
Intent := TJIntent.Create;
Intent.setClass(SharedActivityContext, SharedActivityContext.getClass);
Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_SINGLE_TOP or TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP);
Intent.setAction(TJFMXNotificationAlarm.JavaClass.ACTION_FMX_NOTIFICATION);
notification.setLatestEventInfo(MainActivity.getApplicationContext, StrToJCharSequence('Title'), StrToJCharSequence('Text'), TJPendingIntent.JavaClass.getActivity(SharedActivityContext, TGeneratorUniqueID.GenerateID, Intent, 0));
Service.startForeground(1, notification);
end;
출처 : http://codeverge.com/embarcadero.delphi.firemonkey/help-with-android-firemonkey-st/1058681
노란색으로 표시한 부분에 [TJFMXNotificationAlarm] 은 어떤 라이브러리를 Uses 해야되는지 찾지못해
주석처리하고 사용해보았지만 실패했습니다.
참고될만한 조언 부탁드립니다.
감사합니다.
댓글 1
-
silkroad99
2019.11.20 18:58
추천:1 댓글
Delphi 안드로이드 ForeGround Service 사용법
2019.01.28 14:06
본 게시판은 개발자들이 자유롭게 질문과 답변을 공유하는 게시판입니다.
* 따라서 최대한 정중하게 질문을 올려 주세요.
* 질문을 상세히 작성해 주실 수록 좋은 답변이 올라 옵니다.
* 다른 분들도 참고할 수 있도록 결과 댓글 필수(또는 감사 댓글)
(결과 댓글을 달지 않는 경우 다음 질문에 대한 답변이 달리지 않는 불이익이 있을 수 있습니다.)
-----------------------------------------------------------------------------------------------
안녕하세요
안드로이드 앱개발 새내기 입니다.
다름이 아니라 이번에 개발하는 어플에 한가지 문제점이 있어 문의 드립니다.
델파이 10.2 도쿄버전으로 개발중입니다.
서버와 스마트폰어플로 TCP/IP 통신을 하는게 주된 어플리케이션입니다.
근데 안드로이드5 이상 버전에서는 스마트폰의 홈버튼으로 어플을 감춰놓으면 3~4분후에 종료됩니다.
종료와 동시에 TCP/IP 커넥션이 끊기게 되어 개발된 앱을 사용할수가 없는 상황입니다.
구글검색으로 한가지 방법을 찾아 StartForegroundService라는 안드로이드 서비스를 찾아냈지만,
델파이로 사용된 정확한 예시소스를 찾을수 없어 계속 실패하고 있습니다.
혹시 자바가 아닌 델파이로 구현된 StartForeground 기능을 알고계시다면 도움을 주시길 부탁드립니다.
구글검색으로 찾았던 소스도 같이 올려드립니다.
type
TGeneratorUniqueID = class
const
SETTINGS_NOTIFICATION_UNIQUE_ID = 'SETTINGS_NOTIFICATION_UNIQUE_ID2';
strict private
class var FNextUniqueID: Int64;
public
class constructor Create;
class function GenerateID: Integer;
end;
const
FMX_NOTIFICATION_CENTER = 'FMX_NOTIFICATION_CENTER2';
class constructor TGeneratorUniqueID.Create;
var
Preference: JSharedPreferences;
begin
Preference := SharedActivity.getSharedPreferences(StringToJString(FMX_NOTIFICATION_CENTER), TJContext.JavaClass.MODE_PRIVATE);
FNextUniqueID := Preference.getInt(StringToJString(SETTINGS_NOTIFICATION_UNIQUE_ID), 0);
end;
class function TGeneratorUniqueID.GenerateID: Integer;
var
PreferenceEditor: JSharedPreferences_Editor;
Preference: JSharedPreferences;
begin
Preference := SharedActivity.getPreferences(TJContext.JavaClass.MODE_PRIVATE);
PreferenceEditor := Preference.edit;
try
PreferenceEditor.putInt(StringToJString(SETTINGS_NOTIFICATION_UNIQUE_ID), FNextUniqueID);
finally
PreferenceEditor.commit;
end;
Result := FNextUniqueID;
Inc(FNextUniqueID);
end;
//* My code
procedure TFormMain.SetForeground;
var
Service: JService;
notification: JNotification;
NotificationCompat_Builder: JNotificationCompat_Builder;
Intent: JIntent;
begin
NotificationCompat_Builder := TJNotificationCompat_Builder.Create;
NotificationCompat_Builder := NotificationCompat_Builder.setSmallIcon(SharedActivityContext.getApplicationInfo.icon);
NotificationCompat_Builder := NotificationCompat_Builder.setContentTitle(StrToJCharSequence(GetApplicationTitle));
NotificationCompat_Builder := NotificationCompat_Builder.setContentText(StrToJCharSequence('Body'));
notification := NotificationCompat_Builder.build;
Intent := TJIntent.Create;
Intent.setClass(SharedActivityContext, SharedActivityContext.getClass);
Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_SINGLE_TOP or TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP);
Intent.setAction(TJFMXNotificationAlarm.JavaClass.ACTION_FMX_NOTIFICATION);
notification.setLatestEventInfo(MainActivity.getApplicationContext, StrToJCharSequence('Title'), StrToJCharSequence('Text'), TJPendingIntent.JavaClass.getActivity(SharedActivityContext, TGeneratorUniqueID.GenerateID, Intent, 0));
Service.startForeground(1, notification);
end;
출처 : http://codeverge.com/embarcadero.delphi.firemonkey/help-with-android-firemonkey-st/1058681
노란색으로 표시한 부분에 [TJFMXNotificationAlarm] 은 어떤 라이브러리를 Uses 해야되는지 찾지못해
주석처리하고 사용해보았지만 실패했습니다.
참고될만한 조언 부탁드립니다.
감사합니다.
댓글 1
-
silkroad99
2019.11.20 18:58
추천:1 댓글
안녕하세요
저도 이번에 10.3.3 베타버젼으로 테스트해 보니 문제는 두가지인듯합니다.
android api 28 입니다.
1. foreground 변경
2. power 최적화 상태해제
참고로 29버젼에서는 AndroidManifest.template.xml 파일에서
AndroidManifest.template.xml에서
<service
android:name="android.app.lib_name"
android:value="%libNameValue%"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="connectedDevice|dataSync|location|mediaPlayback|phoneCall">
</service>
파일을 추가해주셔야 합니다.
1번해결방법: FIsForeground 전역변수 설저
procedure TServiceModule.StartForeground;
begin
if FIsForeground then Exit;
EnableWakeLock(True);
if TJBuild_VERSION.JavaClass.SDK_INT > TJBuild_VERSION_CODES.JavaClass.O then
begin // 28 > 26
ServiceChannel := TJNotificationChannel.JavaClass.init(StringtoJString(CHANNEL_ID),
StrToJCharSequence('Location Service Channel'),
TJNotificationManager.JavaClass.IMPORTANCE_DEFAULT);
Obj := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.NOTIFICATION_SERVICE);
NotificationManager := TJNotificationManager.Wrap(Obj);
NotificationManager.createNotificationChannel(ServiceChannel);
PendingIntent := TJPendingIntent.JavaClass.getActivity(JavaService.getApplicationContext, 0, gDM_Intent, 0);
ncb := TJNotificationCompat_Builder.JavaClass.init(TAndroidHelper.Context, StringToJString(CHANNEL_ID));
ncb.setContentTitle(StrToJCharSequence('Location Service'));
ncb.setTicker(StrToJCharSequence('Communications Service'));
ncb.setSmallIcon(JavaService.getApplicationInfo.icon);
ncb.setContentIntent(PendingIntent);
ncb.setOngoing(True);
ntf := ncb.build;
end
else
begin
// earlier notification code (worked under 10.2.3, targetting API 14)
PendingIntent := TJPendingIntent.JavaClass.getActivity(JavaService.getApplicationContext, 0, gDM_Intent, 0);
ntf := TJNotification.Create;
ntf.icon := JavaService.getApplicationInfo.icon;
ntf.setLatestEventInfo(JavaService.getApplicationContext, StrToJCharSequence('Location Service'),
StrToJCharSequence('Communications Service'), PendingIntent);
end;
JavaService.startForeground(gDM_StartId, ntf);
FIsForeground := True;
end;
2번해결방법:
procedure TMainDataModule.Device_Battery_Permission_Checking;
begin
{$IFDEF ANDROID}
TPermissionsService.DefaultService.RequestPermissions([cPermissionRequest_Ignore_Battery_Optimizations], Battery_statePermissionsResultHandler);
//PermissionsService.RequestPermissions([JStringToString(TJManifest_permission.JavaClass.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)],
// procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>)
// begin
// if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
// begin
// {Device Telephone Number }
// end
// else
// begin
// TDialogService.ShowMessage('배터리 권한을 설정하세요');
// end;
// end)
{$ENDIF}
end;
procedure TMainDataModule.Battery_statePermissionsResultHandler(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
begin
if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
begin
{Device Battery }
end
else
begin
//TDialogService.ShowMessage('배터리 권한을 설정하세요');
end;
end;
procedure TMainDataModule.Login_Global_Fix_Load;
var
Sender : TObject;
provider:string;
Settings_secure:TJSettings_Secure;
Intent:JIntent;
packageName:string;
pw:JPowerManager;
begin
Intent := TJIntent.Create;
packageName:= JStringtoString(TAndroidHelper.Context.getPackageName());
pw:=GetPowerManager;
if pw.isIgnoringBatteryOptimizations(TAndroidHelper.Context.getPackageName)=true then
begin
Intent.setAction(TJSettings.javaClass.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
//TAndroidHelper.Context.startActivity(Intent);
end
else
begin
Intent.setAction(TJSettings.javaClass.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
Intent.setData(TJnet_Uri.JavaClass.parse(StringToJString('package:'+packageName)));
TAndroidHelper.Context.startActivity(Intent);
end;
.............
...........
end;
제가 테스트해본결과 이상없이 잘 됩니다.
수고하세요