on
android 개발해 보기 sms 일괄 전송...
android 개발해 보기 sms 일괄 전송...
반응형
아무래도 휴대폰에 앱을 개발하는 일이다 보니, 문자 전송 같은 기본 기능을 이용하는 앱을 개발하는 일이 많기는 하다. 요새는 카카오톡등을 이용하거나, FCM 등을 이용해서 알림을 보내는 기능등을 구현해 보지만, 예전 방식 처럼 SMS 을 전송해 보는 것도 오랜만 이기는 하다.
구글이 계정 정책등으로 인해 앱을 등록할 때 기본앱으로 사용할 수 없는 SMS 앱은 등록에 무리가 있다. 그래서 그냥 개인적으로 사용하기 위해서 기본앱 기능은 아니지만, 필요에 의한 문자 전송을 구현하는 앱을 만들어 볼 까 싶다.
먼저 앱을 구동하기 위해서는 Manifest 파일에 권한 설정을 등록해 준다.
......
SMS 발송 권한을 설정했으니, 앱을 실행하면서 실제 동작이 발생 하기 전에 사용자에게 권한을 획득 하는 코드를 activity 에 넣어 보자.
import android.Manifest; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.pm.PackageManager; import android.database.Cursor; import android.os.Bundle; import android.telephony.SmsManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.navigation.fragment.NavHostFragment; import com.example.smssend0823.Database.DBHandler; import com.example.smssend0823.Database.MsgTargetBean; import com.example.smssend0823.Database.SendMessageAdapter; import com.example.smssend0823.Database.SendMessageBean; import com.example.smssend0823.Utils.OnBackPressedListener; import com.example.smssend0823.databinding.FragmentMsgselectBinding; import java.util.ArrayList; public class MsgSelectFragment extends Fragment implements OnBackPressedListener { private static final String TAG = "MsgSelectFragment"; private FragmentMsgselectBinding binding; ArrayList beans; SendMessageAdapter adapter; DBHandler dbHandler ; String phoneNo ; String message ; private static final int PERMISSION_RQST_SEND = 101; public static Fragment newInstance() { MsgSelectFragment fragment = new MsgSelectFragment(); return fragment; } @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) { binding = FragmentMsgselectBinding.inflate(inflater, container, false); return binding.getRoot(); } public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); beans = new ArrayList<>(); doDisplaySendMessage(); binding.listSendMessage.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { int iCnt = 0 ; for(int i=0; i < beans.size() ; i++) { if (beans.get(i).isSelectedMsg()) iCnt++; } if (iCnt > 0) { beans.get(position).setSelectedMsg(false); adapter.notifyDataSetChanged(beans); Toast.makeText(getContext(), iCnt +"개 이상 선택할 수 없습니다.", Toast.LENGTH_SHORT).show(); return; } beans.get(position).setSelectedMsg(!beans.get(position).isSelectedMsg()); adapter.notifyDataSetChanged(beans); } }); binding.btnSendMessage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = 0 ; int iCnt = 0 ; for(int i=0; i < beans.size() ; i++) { if (beans.get(i).isSelectedMsg()) { position = i; iCnt++; break; }; } if (iCnt == 0) { Toast.makeText(getContext(), "전송할 메시지를 선택하세요.", Toast.LENGTH_SHORT).show(); return; } message = beans.get(position).getSendMessage() ; AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("메시지 전송") .setMessage("[" + beans.get(position).getSendMessage() + "] 로 전송할까요?") .setPositiveButton("확인", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dbHandler = DBHandler.open(getContext()); Cursor rs = dbHandler.selectAll(); while(rs.moveToNext()) { MsgTargetBean msgTargetBean = new MsgTargetBean(); msgTargetBean.setId(rs.getInt(rs.getColumnIndex("_id"))); msgTargetBean.setSendSeqNo(rs.getString(rs.getColumnIndex("sendSeqNo"))); msgTargetBean.setReceivePhoneNum(rs.getString(rs.getColumnIndex("receivePhoneNum"))); msgTargetBean.setSendMessage(rs.getString(rs.getColumnIndex("sendMessage"))); msgTargetBean.setSendTy(rs.getString(rs.getColumnIndex("sendTy"))); if("S".equals(msgTargetBean.getSendTy())) { phoneNo = msgTargetBean.getReceivePhoneNum(); if (sendSMSMessage()) { msgTargetBean.setSendTy("Y"); msgTargetBean.setSendMessage(message); dbHandler.update(msgTargetBean); } } } dbHandler.close(); } }) .setNegativeButton("취소", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog = builder.create(); dialog.show(); } }); } private void doDisplaySendMessage() { beans.clear(); dbHandler = DBHandler.open(getContext()); Cursor rs = dbHandler.selectMsgAll(); while (rs.moveToNext()) { SendMessageBean bean = new SendMessageBean(); bean.setSendMessage(rs.getString(rs.getColumnIndex("messageString"))); beans.add(bean); } adapter = new SendMessageAdapter(beans, getContext()); adapter.notifyDataSetChanged(beans); binding.listSendMessage.setAdapter(adapter); } protected boolean sendSMSMessage() { if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getContext(), "SMS 전송 권한에 대한 허가가 필요합니다.", Toast.LENGTH_SHORT).show(); if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),Manifest.permission.SEND_SMS)) { Log.e(TAG, "shouldShowRequestPermissionRationale"); } else { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.SEND_SMS}, PERMISSION_RQST_SEND); Log.e(TAG, "requestPermissions"); } } else { SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(phoneNo, null, message, null, null); Toast.makeText(getContext(), "메시지가 전송 되었습니다.",Toast.LENGTH_LONG).show(); return true ; } return false; } //Now once the permission is there or not would be checked @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSION_RQST_SEND: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { } else {Toast.makeText(getContext(), "SMS 발송이 되지 않았습니다. 잠시 뒤에 다시 시도 하세요.", Toast.LENGTH_LONG).show(); return; } } } } @Override public void onDestroyView() { super.onDestroyView(); binding = null; } @Override public void onBackPressed() { getParentFragmentManager().beginTransaction() .replace(R.id.container, MsgSendListFragment.newInstance()) .commitNow(); } }
source code 의 예시와 같이 sendSMSMessage() 함수에는 메시지 발송전에 권한 획득 여부를 확인하고, 권한이 없다면 사용자에게 권한 허가를 요청하는 알림을 띄워 권한을 획득 하게 된다.
반응형
다만, 이런 기능을 앱으로 이용하려면 playstore 에는 등록에 제한이 있으므로 다른 스토어를 이용하여야 한다.
SMS을 보내는 다른 방법은 권한 없이 사용할 수 있는 SMS Retriever API 을 활용하는 방법이 있다고 할 수 있는데, 실제 앱을 개발하다 보면 불편한 사항이 생기게 되어 있다.
https://developers.google.com/identity/sms-retriever/overview
참고해서 보면 좋을 것 깥다.
반응형
from http://billcorea.tistory.com/60 by ccl(A) rewrite - 2021-09-06 14:01:05